问题
I'm developing an application in React.Js.
I have the array:
array = [
{
"id": 1,
"date": {
"id": 1,
"name": "202001"
},
"item": {
"id": 1,
"name": "I1"
},
"price": 100
},
{
"id": 2,
"date": {
"id": 2,
"name": "202002"
},
"item": {
"id": 1,
"name": "I1"
},
"price": 200
},
{
"id": 3,
"date": {
"id": 2,
"name": "202002"
},
"item": {
"id": 2,
"name": "I2"
},
"price": 300
},
]
And I show the data as shown in the table:
ITEM | 202001 | 202002 | TOTAL |
---|---|---|---|
I1 | 100 | 200 | 300 |
I2 | - | 300 | 300 |
TOTAL | 100 | 500 | 600 |
And I did this to get those values:
items_dicc = array.reduce((acc, e) => {
if (!acc[e["item"]["name"]]) {
acc[e["item"]["name"]] = {
[e["date"]["name"]]: e["price"]
}
} else {
acc[e["item"]["name"]][e["date"]["name"]] = e["price"]
}
return acc
}, {})
dates = [...new Set(Object.keys(items_dicc).map(i => Object.keys(items_dicc[i])).flat())]
totalSumPerDate = {};
dates.forEach(date => {
const sumOnDate = Object.values(items_dicc).reduce((acc, curr) => {
acc = acc + (curr[date]? curr[date] : 0);
return acc;
}, 0);
totalSumPerDate[[date]] = sumOnDate;
});
totalSum = Object.values(totalSumPerDate).reduce((acc, curr) => acc+curr, 0);
sumPerItem = {};
Object.keys(items_dicc).forEach(key => {
const sum = Object.values(items_dicc[key]).reduce((acc, curr) => acc + curr, 0);
sumPerItem[[key]] = sum;
});
<table>
<thead>
<tr>
<th>ITEM</th>
{dates.map(date => <th>{date}</th>)}
<th>TOTAL</th>
</tr>
</thead>
<tbody>
{
Object.keys(items_dicc).map((item) => {
return (
<tr>
<td>{item}</td>
{dates.map((date) => <td>{items_dicc[item][date] || ''}</td>)}
<td>{sumPerItem[item]}</td>
</tr>
)
})
}
<tr>
<td>TOTAL</td>
{Object.values(totalSumPerDate).map(item => <td>{item}</td>)}
<td>{totalSum}</td>
</tr>
</tbody>
</table>
I need to be able to show through a popup other data that the array may contain (for example the id).
I understand that to do this it is necessary to create a local state in the component to update the details when clicking on the selected record and pass the state to the modal.
It should also be able to bring in the totals info.
How can I do it, suggestions?
回答1:
You can pass the total data to the onClickEventHandler like this,
<tr onClick={(event) => yourHandler(event, item, sumPerItem[item])}>
<td>{item}</td>
{dates.map((date) => <td>{items_dicc[item][date] || ''}</td>)}
<td>{sumPerItem[item]}</td>
</tr>
The event handler should be written like this,
yourHandler = (event, currentItem, totalForRow) => {
// You update the state here
}
This method is for whole row. If you want to show different data on each cell click you need to add the eventHandler on elements and update the method parameters according to your need.
回答2:
Try this approach,
You have to create a local state for the selected record of the table row and pass it to the modal component. Update the selected record on click of the table row.
import React, { useState } from "react";
import "./styles.css";
import "bootstrap/dist/css/bootstrap.min.css";
const array = [
{
id: 1,
date: {
id: 1,
name: "202001"
},
item: {
id: 1,
name: "I1"
},
price: 100
},
{
id: 2,
date: {
id: 2,
name: "202002"
},
item: {
id: 1,
name: "I1"
},
price: 200
},
{
id: 3,
date: {
id: 2,
name: "202002"
},
item: {
id: 2,
name: "I2"
},
price: 300
}
];
export default function App() {
const [show, setShow] = useState(false);
const [selectedData, setSelectedData] = useState({});
const hanldeClick = (selectedId) => {
const selectedRec = array.find((val) => val.item.name === selectedId);
setSelectedData(selectedRec);
setShow(true);
};
const hideModal = () => {
setShow(false);
};
const items_dicc = array.reduce((acc, e) => {
if (!acc[e["item"]["name"]]) {
acc[e["item"]["name"]] = {
[e["date"]["name"]]: e["price"]
};
} else {
acc[e["item"]["name"]][e["date"]["name"]] = e["price"];
}
return acc;
}, {});
const dates = [
...new Set(
Object.keys(items_dicc)
.map((i) => Object.keys(items_dicc[i]))
.flat()
)
];
const totalSumPerDate = {};
dates.forEach((date) => {
const sumOnDate = Object.values(items_dicc).reduce((acc, curr) => {
acc = acc + (curr[date] ? curr[date] : 0);
return acc;
}, 0);
totalSumPerDate[[date]] = sumOnDate;
});
const totalSum = Object.values(totalSumPerDate).reduce(
(acc, curr) => acc + curr,
0
);
const sumPerItem = {};
Object.keys(items_dicc).forEach((key) => {
const sum = Object.values(items_dicc[key]).reduce(
(acc, curr) => acc + curr,
0
);
sumPerItem[[key]] = sum;
});
return (
<>
<table>
<thead>
<tr>
<th>ITEM</th>
{dates.map((date) => (
<th>{date}</th>
))}
<th>TOTAL</th>
</tr>
</thead>
<tbody>
{Object.keys(items_dicc).map((item) => {
return (
<tr onClick={() => hanldeClick(item)}>
<td>{item}</td>
{dates.map((date) => (
<td>{items_dicc[item][date] || ""}</td>
))}
<td>{sumPerItem[item]}</td>
</tr>
);
})}
<tr>
<td>TOTAL</td>
{Object.values(totalSumPerDate).map((item) => (
<td>{item}</td>
))}
<td>{totalSum}</td>
</tr>
</tbody>
</table>
{show && <Modal details={selectedData} handleClose={hideModal} />}
</>
);
}
const Modal = ({ handleClose, details }) => {
console.log(details);
return (
<div className="modal display-block">
<section className="modal-main">
<div className="App">
<table class="table">
<thead>
<tr>
<th scope="col">ITEM</th>
<th scope="col">ID</th>
<th scope="col">DATE</th>
<th scope="col">PRICE</th>
</tr>
</thead>
<tbody>
<tr>
<td>{details?.item?.name}</td>
<td>{details?.item?.id}</td>
<td>{details?.date?.name}</td>
<td>{details?.price}</td>
</tr>
</tbody>
</table>
</div>
<button onClick={handleClose}>close</button>
</section>
</div>
);
};
Working code - https://codesandbox.io/s/adoring-moore-rsn97?file=/src/App.js:0-3665
来源:https://stackoverflow.com/questions/65390482/show-a-pop-up-window-with-information-coming-from-an-element-and-its-totals-fro