Моя проблема заключается в том, что когда я ввожу значения количества и цены для расчета итоговой суммы, она будет рассчитана, но когда я добавляю еще одну строку, итоговое значение рассчитывается на основе последних введенных значений количества и цены, как показано на рисунке ниже:
Мой код ниже:
class AjouterFacture extends Component {
constructor(props) {
super(props);
this.state = {
rowData: [],
Produits: [],
Quantite: "",
Prix: ""
};
this.handleRowChange = this.handleRowChange.bind(this);
this.handleRowDelete = this.handleRowDelete.bind(this);
this.handleRowAdd = this.handleRowAdd.bind(this);
this.getTotal = this.getTotal.bind(this);
this.pushToCaller = this.pushToCaller.bind(this);
}
handleQuantiteChange(e) {
this.setState({
Quantite: e.target.value
}, this.pushToCaller);
}
handleselectprdtChange(e) {
this.setState({
selectprdt: e.target.value
}, this.pushToCaller);
}
handlePrixChange(e) {
this.setState({
Prix: e.target.value
}, this.pushToCaller);
}
pushToCaller() {
this.handleRowChange( {
Quantite: parseInt(this.state.Quantite, 10),
selectprdt: this.state.selectprdt,
Prix: parseFloat(this.state.Prix),
});
}
render() {
return (<div className = "animated fadeIn">
<h6> Veuillez ajouter au moins un produit : </h6>
<Table >
<thead >
<tr>
<th>PRODUIT</th>
<th>QUANTITE</th>
<th>PRIX UNITAIRE</th>
<th>TOTAL</th>
<th></th>
</tr>
</thead>
<tbody>
{this.state.rowData.map((index) =>
<tr key = {index} id = {index}
onChange = {this.handleRowChange}>
<td> <Input type = "select" name = "selectedcl" id = "selectcl"
placeholder = "Veuillez sélectionner un produit" value = {this.state.rowData.selectprdt}
onChange = {this.handleselectprdtChange} >
<option key = {-1} hidden>Choisisr un produit</option>
{ this.state.Produits.map((pdt, i) =>
<option key = {i} >{pdt.Nomp}</option>
)}
</Input>
</td>
<td><Input type = "number"
placeholder = "0" value = {this.state.rowData.Quantite} onChange = {this.handleQuantiteChange}/></td>
<td>
<InputGroup ><Input type = "text"
value = {this.state.rowData.Prix} onChange = {this.handlePrixChange} />
<InputGroupAddon addonType = "prepend">
<InputGroupText><i ></i></InputGroupText>
</InputGroupAddon>
</InputGroup >
</td>
<td >
<p >{this.state.Quantite * this.state.Prix} </p>
</td>
<td>
<Button onClick = {this.handleRowDelete} active style = {center} >Effacer</Button>
</td> </tr> )}
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td><Button onClick = {this.handleRowAdd} >Ajouter une ligne</Button></td>
</tr>
</tbody>
<tfoot>
<tr>
<th></th>
<th >Grand total :</th>
<th>{this.getTotal()} </th>
<th></th>
</tr>
</tfoot>
</Table>
</div>);
}
getTotal() {
let grandTotal = 0;
const rowTotals = this.state.rowData.map(row => this.state.Quantite * this.state.Prix);
if (rowTotals.length > 0) {
grandTotal = rowTotals.reduce((acc, val) => acc + val);
}
return grandTotal;
}
handleRowChange(row, data) {
const rowDataCopy = this.state.rowData.slice(0);
rowDataCopy[row] = data;
this.setState({
rowData: rowDataCopy
});
}
handleRowDelete(row) {
const rowDataCopy = this.state.rowData.slice(0);
rowDataCopy.splice(row, 1);
this.setState({
rowData: rowDataCopy
});
}
handleRowAdd() {
const rowDataCopy = this.state.rowData.slice(0);
rowDataCopy.push({selectprdt:'', Quantite : "", Prix :"" });
this.setState({
rowData: rowDataCopy
});
}
}
export default AjouterFacture;
Я хочу, чтобы итоговый столбец рассчитывался для каждой строки.
Как я могу это исправить?
🤔 А знаете ли вы, что...
JavaScript имеет множество библиотек и фреймворков, таких как jQuery, Angular, и Vue.js.
Попробуйте обновить код ниже.
class AjouterFacture extends Component {
constructor(props) {
super(props);
this.state = {
rowData: [],
Produits: [],
Quantite: "",
Prix: "",
id:0
};
this.handleRowChange = this.handleRowChange.bind(this);
this.handleRowDelete = this.handleRowDelete.bind(this);
this.handleRowAdd = this.handleRowAdd.bind(this);
this.getTotal = this.getTotal.bind(this);
this.pushToCaller = this.pushToCaller.bind(this);
}
handleQuantiteChange(e) {
this.setState({
Quantite: e.target.value
}, this.pushToCaller);
}
handleselectprdtChange(e) {
this.setState({
selectprdt: e.target.value
}, this.pushToCaller);
}
handlePrixChange(e) {
this.setState({
Prix: e.target.value
}, this.pushToCaller);
}
pushToCaller() {
this.handleRowChange(this.state.id, {
Quantite: parseInt(this.state.Quantite, 10),
selectprdt: this.state.selectprdt,
Prix: parseFloat(this.state.Prix),
});
}
render() {
return (<div className = "animated fadeIn">
<h6> Veuillez ajouter au moins un produit : </h6>
<Table >
<thead >
<tr>
<th>PRODUIT</th>
<th>QUANTITE</th>
<th>PRIX UNITAIRE</th>
<th>TOTAL</th>
<th></th>
</tr>
</thead>
<tbody>
{this.state.rowData.map((index) =>
<tr key = {index} id = {index}
onChange = {this.handleRowChange}>
<td> <Input type = "select" name = "selectedcl" id = "selectcl"
placeholder = "Veuillez sélectionner un produit" value = {this.state.rowData.selectprdt}
onChange = {this.handleselectprdtChange} >
<option key = {-1} hidden>Choisisr un produit</option>
{ this.state.Produits.map((pdt, i) =>
<option key = {i} >{pdt.Nomp}</option>
)}
</Input>
</td>
<td><Input type = "number"
placeholder = "0" value = {this.state.rowData.Quantite} onChange = {this.handleQuantiteChange}/></td>
<td>
<InputGroup ><Input type = "text"
value = {this.state.rowData.Prix} onChange = {this.handlePrixChange} />
<InputGroupAddon addonType = "prepend">
<InputGroupText><i ></i></InputGroupText>
</InputGroupAddon>
</InputGroup >
</td>
<td >
<p >{this.state.Quantite * this.state.Prix} </p>
</td>
<td>
<Button onClick = {this.handleRowDelete} active style = {center} >Effacer</Button>
</td> </tr> )}
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td><Button onClick = {this.handleRowAdd} >Ajouter une ligne</Button></td>
</tr>
</tbody>
<tfoot>
<tr>
<th></th>
<th >Grand total :</th>
<th>{this.getTotal()} </th>
<th></th>
</tr>
</tfoot>
</Table>
</div>);
}
getTotal() {
let grandTotal = 0;
const rowTotals = this.state.rowData.map(row => this.state.Quantite * this.state.Prix);
if (rowTotals.length > 0) {
grandTotal = rowTotals.reduce((acc, val) => acc + val);
}
return grandTotal;
}
handleRowChange(row, data) {
const rowDataCopy = this.state.rowData.slice(0);
rowDataCopy[row] = data;
this.setState({
rowData: rowDataCopy
});
}
handleRowDelete(row) {
const rowDataCopy = this.state.rowData.slice(0);
rowDataCopy.splice(row, 1);
this.setState({
rowData: rowDataCopy
});
}
handleRowAdd() {
let id = this.state.id;
id = id++;
const rowDataCopy = this.state.rowData.slice(0);
rowDataCopy.push({selectprdt:'', Quantite : "", Prix :"" });
this.setState({
rowData: rowDataCopy,
id: id
});
}
}
export default AjouterFacture;
У вас есть несколько проблем с предоставленным вами кодом, я постараюсь перечислить большинство из них ниже:
Вы не связали несколько методов:
this.handleQuantiteChange = this.handleQuantiteChange.bind(this);
this.handlePrixChange = this.handlePrixChange.bind(this);
this.handleselectprdtChange = this.handleselectprdtChange.bind(this);
В итоговом столбце вы должны вывести цену именно этой строки, а не временных переменных. Вы также должны указать цену / количество в конкретной строке.
Функция map
вызывает с (data, index)
, а не только с (index)
.
Вам необходимо связать index
с вызовом обработчика onChange
, чтобы получить целевую строку. То же самое и с handleRowDelete
.
Вот ваш исправленный код:
class AjouterFacture extends React.Component {
constructor(props) {
super(props);
this.state = {
rowData: [],
Produits: [],
id: 0
};
this.handleQuantiteChange = this.handleQuantiteChange.bind(this);
this.handlePrixChange = this.handlePrixChange.bind(this);
this.handleselectprdtChange = this.handleselectprdtChange.bind(this);
this.handleRowDelete = this.handleRowDelete.bind(this);
this.handleRowAdd = this.handleRowAdd.bind(this);
this.getTotal = this.getTotal.bind(this);
}
handleQuantiteChange(index, value) {
const rowDataCopy = this.state.rowData.slice(0);
rowDataCopy[index] = Object.assign({}, rowDataCopy[index], {Quantite: parseInt(value, 10)});
this.setState({
rowData: rowDataCopy
});
}
handleselectprdtChange(index, value) {
const rowDataCopy = this.state.rowData.slice(0);
rowDataCopy[index] = Object.assign({}, rowDataCopy[index], {selectprdt: value});
this.setState({
rowData: rowDataCopy
});
}
handlePrixChange(index, value) {
const rowDataCopy = this.state.rowData.slice(0);
rowDataCopy[index] = Object.assign({}, rowDataCopy[index], {Prix: parseInt(value, 10)});
this.setState({
rowData: rowDataCopy
});
}
render() {
return (
<div className = "animated fadeIn">
<h6> Veuillez ajouter au moins un produit : </h6>
<Table>
<thead>
<tr>
<th>PRODUIT</th>
<th>QUANTITE</th>
<th>PRIX UNITAIRE</th>
<th>TOTAL</th>
<th />
</tr>
</thead>
<tbody>
{this.state.rowData.map((data, index) => (
<tr key = {index} id = {index}>
<td>
{" "}
<Input
type = "select"
name = "selectedcl"
id = "selectcl"
placeholder = "Veuillez sélectionner un produit"
value = {data.selectprdt}
onChange = {(e) => this.handleselectprdtChange(index, e.targe.value)}
>
<option key = {-1} hidden>
Choisisr un produit
</option>
{this.state.Produits.map((pdt, i) => (
<option key = {i}>{pdt.Nomp}</option>
))}
</Input>
</td>
<td>
<Input
type = "number"
placeholder = "0"
value = {data.Quantite || 0}
onChange = {(e) => this.handleQuantiteChange(index, e.target.value)}
/>
</td>
<td>
<InputGroup>
<Input
type = "text"
value = {data.Prix || 0}
onChange = {(e) => this.handlePrixChange(index, e.target.value)}
/>
<InputGroupAddon addonType = "prepend">
<InputGroupText>
<i />
</InputGroupText>
</InputGroupAddon>
</InputGroup>
</td>
<td>
<p>{(data.Quantite || 0) * (data.Prix || 0)} </p>
</td>
<td>
<Button
onClick = {(e) => this.handleRowDelete(index)}
active
style = {"center"}
>
Effacer
</Button>
</td>{" "}
</tr>
))}
<tr>
<td />
<td />
<td />
<td />
<td>
<Button onClick = {this.handleRowAdd} style = {center}>Ajouter une ligne</Button>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<th />
<th>Grand total :</th>
<th>{this.getTotal()} </th>
<th />
</tr>
</tfoot>
</Table>
</div>
);
}
getTotal() {
let grandTotal = 0;
const rowTotals = this.state.rowData.map(
row => (row.Quantite * row.Prix) || 0
);
if (rowTotals.length > 0) {
grandTotal = rowTotals.reduce((acc, val) => acc + val);
}
return grandTotal;
}
handleRowDelete(row) {
const rowDataCopy = this.state.rowData.slice(0);
rowDataCopy.splice(row, 1);
this.setState({
rowData: rowDataCopy
});
}
handleRowAdd() {
let id = this.state.id;
id = id++;
const rowDataCopy = this.state.rowData.slice(0);
rowDataCopy.push({
selectprdt: "",
Quantite: 0,
Prix: 0
});
this.setState({
rowData: rowDataCopy,
id: id
});
}
}
export default AjouterFacture;