如何在 React JS 中动态 add/delete table 行
How to dynamically add/delete table rows in ReacjJS
我正在尝试使用 ReactJS
动态添加和删除 table
行。
但问题是一旦我添加了几行,即使我随机更改它们,每一行中每一列中的值都是相同的。
下面的屏幕截图将进一步阐明我的问题。
我要做的步骤是:
1) Select 来自下拉列表的 item
2) 输入qty
3) 按 +
按钮
有效,但下次我尝试 select 一个项目或输入一个项目的数量时,它 updates every column
这是我的代码示例:
import React, { Component } from "react";
import {
MDBRow,
MDBCol,
MDBCard,
MDBCardBody,
MDBMask,
MDBIcon,
MDBView,
MDBBtn,
MDBTable,
MDBTableBody,
MDBTableHead,
MDBContainer
} from "mdbreact";
import { NavLink } from "react-router-dom";
import GetTable from "./table";
import GetTable2 from "./table2";
export default class CreateInvoiceForm extends Component {
constructor(props) {
super(props);
this.state = {
vendorName: "",
itemID: "",
qty: "",
rows: [{}]
};
this.onSubmit = this.onSubmit.bind(this);
this.vendorOnChange = this.vendorOnChange.bind(this);
this.itemorOnChange = this.itemorOnChange.bind(this);
this.quantityOnChange = this.quantityOnChange.bind(this);
this.onHandleAddRow = this.onHandleAddRow.bind(this);
}
onHandleAddRow() {
const itemDetails = {
itemID: this.state.itemID,
itemName: "",
qty: this.state.qty,
unitPrice: "",
linePrice: ""
};
this.setState({
rows: [...this.state.rows, itemDetails]
});
}
onSubmit(e) {
e.preventDefault();
alert(this.state.vendorName);
}
vendorOnChange(e) {
this.setState({
vendorName: e.target.value
});
}
quantityOnChange(e) {
this.setState({
qty: e.target.value
});
}
itemorOnChange(e) {
this.setState({
itemID: e.target.value
});
}
render() {
return (
<div>
<MDBCard className="my-12 px-12 pb-12">
<MDBCardBody className="">
<h2 className="h1-responsive font-weight-bold text-center my-5">
Create a Purchase Invoice
</h2>
<p className="text-center w-responsive mx-auto mb-5">
Creating purchase invoices
<strong>Without having a Purchase Order</strong>
</p>
{/* form starts here */}
<form onSubmit={this.onSubmit}>
<MDBRow>
<MDBCol lg="6" md="6" className="mb-lg-0 mb-6">
<p className="h6 mb-4">
{" "}
<i className="fa fa-info-circle"></i> Invoice Details
</p>
<label
htmlFor="defaultFormRegisterNameEx"
className="grey-text"
>
Invoice No:
</label>
<input
type="text"
id="defaultFormRegisterNameEx"
className="form-control"
/>
<br />
<label
htmlFor="defaultFormRegisterEmailEx"
className="grey-text"
>
Vendor
</label>
<div class="form-group">
<select
class="form-control"
id="exampleSelect1"
onChange={this.vendorOnChange}
>
<option disabled selected>
- Select vendor -{" "}
</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
</select>
</div>
<label
htmlFor="defaultFormRegisterConfirmEx"
className="grey-text"
>
Invoice Date:
</label>
<input
type="date"
id="defaultFormRegisterConfirmEx"
className="form-control"
/>
<br />
<label
htmlFor="defaultFormRegisterPasswordEx"
className="grey-text"
>
Expected Delievery Date:
</label>
<input
type="date"
id="defaultFormRegisterPasswordEx"
className="form-control"
/>
</MDBCol>
<MDBCol lg="6" md="6" className="mb-lg-0 mb-6">
<p className="h6 mb-4">
{" "}
<i className="fa fa-truck"></i> Delievery Details
</p>
<label
htmlFor="defaultFormRegisterNameEx"
className="grey-text"
>
Billing Address
</label>
<textarea className="form-control"> </textarea>
<label
htmlFor="defaultFormRegisterEmailEx"
className="grey-text"
>
Contact Person:
</label>
<input
type="text"
id="defaultFormRegisterEmailEx"
className="form-control"
/>
<br />
<label
htmlFor="defaultFormRegisterConfirmEx"
className="grey-text"
></label>
<input
hidden
type="email"
id="defaultFormRegisterConfirmEx"
className="form-control"
/>
<br />
<label
htmlFor="defaultFormRegisterPasswordEx"
className="grey-text"
></label>
<input
hidden
type="password"
id="defaultFormRegisterPasswordEx"
className="form-control"
/>
<br />
<br />
<br />
<br />
<br />
<br />
</MDBCol>
</MDBRow>
<hr />
{/* new row======================================================= */}
<MDBRow>
<MDBCol lg="5" md="5" className="mb-lg-0 mb-5 text-center">
<div class="form-group">
<label
htmlFor="defaultFormRegisterEmailEx"
className="grey-text"
>
Select an Item:
</label>
<select class="form-control" onChange={this.itemorOnChange}>
<option disabled selected>
- Select Item -
</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
</select>
</div>
</MDBCol>
<MDBCol lg="5" md="5" className="mb-lg-0 mb-5 text-center">
<div class="form-group">
<label
htmlFor="defaultFormRegisterEmailEx"
className="grey-text"
>
Quantity:
</label>
<input
type="text"
id="defaultFormRegisterEmailEx"
className="form-control"
onChange={this.quantityOnChange}
/>
</div>
</MDBCol>
<MDBCol lg="2" md="2" className="mb-lg-0 mb-2 text-center">
<div className="form-group">
<label
htmlFor="defaultFormRegisterEmailEx"
className="grey-text"
></label>
<button
style={{ height: "40px" }}
name="subject"
type="button"
className="btn btn-success btn-sm form-control"
onClick={this.onHandleAddRow}
>
<i className="fa fa-plus fa-lg"></i>
</button>
</div>
</MDBCol>
</MDBRow>
<MDBRow>
<MDBCol lg="12" md="12" className="mb-lg-0 mb-12 text-center">
<MDBTable
className="container-fluid"
striped
bordered
hover
responsive
>
<MDBTableHead color="primary-color" textWhite>
<tr>
<th>Item ID</th>
<th>Item Name</th>
<th>Qty</th>
<th>Unit Price (R.s)</th>
<th>Line Price (R.s)</th>
<th><i className="fa fa-cog"></i></th>
</tr>
</MDBTableHead>
<MDBTableBody>
{this.state.rows.length > 1
? this.state.rows.map((item, id) => (
<tr key={id}>
<td>{this.state.itemID}</td>
<td>{this.state.itemID}</td>
<td>{this.state.qty}</td>
<td>price</td>
<td>Line</td>
<MDBBtn><i className="fa fa-times"></i></MDBBtn>
</tr>
))
: <tr></tr>
}
</MDBTableBody>
</MDBTable>
</MDBCol>
</MDBRow>
</form>
{/* form ends here */}
</MDBCardBody>
</MDBCard>
<br />
<MDBContainer>
<MDBRow>
<MDBCol className="col-12 col-md-12 text-center">
<GetTable2 />
</MDBCol>
</MDBRow>
</MDBContainer>
</div>
);
}
}
有人可以帮我吗?
qty
和 itemID
有一个状态值,因此它会用一个值呈现每一行。如果您需要每个项目的数量和项目 ID(这似乎是合理的),那么您需要将其保持在状态 per item.
您的 map
应该更改为使用每一行的值,例如 item.qty
(奇怪的是一个字符串),并且您的数量更新应该更改该行的数据。
import React, { Component } from 'react'
class Table extends Component {
constructor(props) {
super(props) //since we are extending class Table so we have to use super in order to override Component class constructor
this.state = { //state is by default an object
students: [
{ id: 1, name: 'Wasif', age: 21, email: 'wasif@email.com' },
{ id: 2, name: 'Ali', age: 19, email: 'ali@email.com' },
{ id: 3, name: 'Saad', age: 16, email: 'saad@email.com' },
{ id: 4, name: 'Asad', age: 25, email: 'asad@email.com' }
]
}
}
render() { //Whenever our class runs, render method will be called automatically, it may have already defined in the constructor behind the scene.
return (
<div>
<h1>React Dynamic Table</h1>
</div>
)
}
}
export default Table //exporting a component make it reusable and this is the beauty of react
我正在尝试使用 ReactJS
动态添加和删除 table
行。
但问题是一旦我添加了几行,即使我随机更改它们,每一行中每一列中的值都是相同的。
下面的屏幕截图将进一步阐明我的问题。
我要做的步骤是:
1) Select 来自下拉列表的 item
2) 输入qty
3) 按 +
按钮
有效,但下次我尝试 select 一个项目或输入一个项目的数量时,它 updates every column
这是我的代码示例:
import React, { Component } from "react";
import {
MDBRow,
MDBCol,
MDBCard,
MDBCardBody,
MDBMask,
MDBIcon,
MDBView,
MDBBtn,
MDBTable,
MDBTableBody,
MDBTableHead,
MDBContainer
} from "mdbreact";
import { NavLink } from "react-router-dom";
import GetTable from "./table";
import GetTable2 from "./table2";
export default class CreateInvoiceForm extends Component {
constructor(props) {
super(props);
this.state = {
vendorName: "",
itemID: "",
qty: "",
rows: [{}]
};
this.onSubmit = this.onSubmit.bind(this);
this.vendorOnChange = this.vendorOnChange.bind(this);
this.itemorOnChange = this.itemorOnChange.bind(this);
this.quantityOnChange = this.quantityOnChange.bind(this);
this.onHandleAddRow = this.onHandleAddRow.bind(this);
}
onHandleAddRow() {
const itemDetails = {
itemID: this.state.itemID,
itemName: "",
qty: this.state.qty,
unitPrice: "",
linePrice: ""
};
this.setState({
rows: [...this.state.rows, itemDetails]
});
}
onSubmit(e) {
e.preventDefault();
alert(this.state.vendorName);
}
vendorOnChange(e) {
this.setState({
vendorName: e.target.value
});
}
quantityOnChange(e) {
this.setState({
qty: e.target.value
});
}
itemorOnChange(e) {
this.setState({
itemID: e.target.value
});
}
render() {
return (
<div>
<MDBCard className="my-12 px-12 pb-12">
<MDBCardBody className="">
<h2 className="h1-responsive font-weight-bold text-center my-5">
Create a Purchase Invoice
</h2>
<p className="text-center w-responsive mx-auto mb-5">
Creating purchase invoices
<strong>Without having a Purchase Order</strong>
</p>
{/* form starts here */}
<form onSubmit={this.onSubmit}>
<MDBRow>
<MDBCol lg="6" md="6" className="mb-lg-0 mb-6">
<p className="h6 mb-4">
{" "}
<i className="fa fa-info-circle"></i> Invoice Details
</p>
<label
htmlFor="defaultFormRegisterNameEx"
className="grey-text"
>
Invoice No:
</label>
<input
type="text"
id="defaultFormRegisterNameEx"
className="form-control"
/>
<br />
<label
htmlFor="defaultFormRegisterEmailEx"
className="grey-text"
>
Vendor
</label>
<div class="form-group">
<select
class="form-control"
id="exampleSelect1"
onChange={this.vendorOnChange}
>
<option disabled selected>
- Select vendor -{" "}
</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
</select>
</div>
<label
htmlFor="defaultFormRegisterConfirmEx"
className="grey-text"
>
Invoice Date:
</label>
<input
type="date"
id="defaultFormRegisterConfirmEx"
className="form-control"
/>
<br />
<label
htmlFor="defaultFormRegisterPasswordEx"
className="grey-text"
>
Expected Delievery Date:
</label>
<input
type="date"
id="defaultFormRegisterPasswordEx"
className="form-control"
/>
</MDBCol>
<MDBCol lg="6" md="6" className="mb-lg-0 mb-6">
<p className="h6 mb-4">
{" "}
<i className="fa fa-truck"></i> Delievery Details
</p>
<label
htmlFor="defaultFormRegisterNameEx"
className="grey-text"
>
Billing Address
</label>
<textarea className="form-control"> </textarea>
<label
htmlFor="defaultFormRegisterEmailEx"
className="grey-text"
>
Contact Person:
</label>
<input
type="text"
id="defaultFormRegisterEmailEx"
className="form-control"
/>
<br />
<label
htmlFor="defaultFormRegisterConfirmEx"
className="grey-text"
></label>
<input
hidden
type="email"
id="defaultFormRegisterConfirmEx"
className="form-control"
/>
<br />
<label
htmlFor="defaultFormRegisterPasswordEx"
className="grey-text"
></label>
<input
hidden
type="password"
id="defaultFormRegisterPasswordEx"
className="form-control"
/>
<br />
<br />
<br />
<br />
<br />
<br />
</MDBCol>
</MDBRow>
<hr />
{/* new row======================================================= */}
<MDBRow>
<MDBCol lg="5" md="5" className="mb-lg-0 mb-5 text-center">
<div class="form-group">
<label
htmlFor="defaultFormRegisterEmailEx"
className="grey-text"
>
Select an Item:
</label>
<select class="form-control" onChange={this.itemorOnChange}>
<option disabled selected>
- Select Item -
</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
</select>
</div>
</MDBCol>
<MDBCol lg="5" md="5" className="mb-lg-0 mb-5 text-center">
<div class="form-group">
<label
htmlFor="defaultFormRegisterEmailEx"
className="grey-text"
>
Quantity:
</label>
<input
type="text"
id="defaultFormRegisterEmailEx"
className="form-control"
onChange={this.quantityOnChange}
/>
</div>
</MDBCol>
<MDBCol lg="2" md="2" className="mb-lg-0 mb-2 text-center">
<div className="form-group">
<label
htmlFor="defaultFormRegisterEmailEx"
className="grey-text"
></label>
<button
style={{ height: "40px" }}
name="subject"
type="button"
className="btn btn-success btn-sm form-control"
onClick={this.onHandleAddRow}
>
<i className="fa fa-plus fa-lg"></i>
</button>
</div>
</MDBCol>
</MDBRow>
<MDBRow>
<MDBCol lg="12" md="12" className="mb-lg-0 mb-12 text-center">
<MDBTable
className="container-fluid"
striped
bordered
hover
responsive
>
<MDBTableHead color="primary-color" textWhite>
<tr>
<th>Item ID</th>
<th>Item Name</th>
<th>Qty</th>
<th>Unit Price (R.s)</th>
<th>Line Price (R.s)</th>
<th><i className="fa fa-cog"></i></th>
</tr>
</MDBTableHead>
<MDBTableBody>
{this.state.rows.length > 1
? this.state.rows.map((item, id) => (
<tr key={id}>
<td>{this.state.itemID}</td>
<td>{this.state.itemID}</td>
<td>{this.state.qty}</td>
<td>price</td>
<td>Line</td>
<MDBBtn><i className="fa fa-times"></i></MDBBtn>
</tr>
))
: <tr></tr>
}
</MDBTableBody>
</MDBTable>
</MDBCol>
</MDBRow>
</form>
{/* form ends here */}
</MDBCardBody>
</MDBCard>
<br />
<MDBContainer>
<MDBRow>
<MDBCol className="col-12 col-md-12 text-center">
<GetTable2 />
</MDBCol>
</MDBRow>
</MDBContainer>
</div>
);
}
}
有人可以帮我吗?
qty
和 itemID
有一个状态值,因此它会用一个值呈现每一行。如果您需要每个项目的数量和项目 ID(这似乎是合理的),那么您需要将其保持在状态 per item.
您的 map
应该更改为使用每一行的值,例如 item.qty
(奇怪的是一个字符串),并且您的数量更新应该更改该行的数据。
import React, { Component } from 'react'
class Table extends Component {
constructor(props) {
super(props) //since we are extending class Table so we have to use super in order to override Component class constructor
this.state = { //state is by default an object
students: [
{ id: 1, name: 'Wasif', age: 21, email: 'wasif@email.com' },
{ id: 2, name: 'Ali', age: 19, email: 'ali@email.com' },
{ id: 3, name: 'Saad', age: 16, email: 'saad@email.com' },
{ id: 4, name: 'Asad', age: 25, email: 'asad@email.com' }
]
}
}
render() { //Whenever our class runs, render method will be called automatically, it may have already defined in the constructor behind the scene.
return (
<div>
<h1>React Dynamic Table</h1>
</div>
)
}
}
export default Table //exporting a component make it reusable and this is the beauty of react