在React的自定义表中选择/取消选择行

时间:2019-01-31 10:03:48

标签: javascript reactjs

我有一个表格组件,每行和标题上都有复选框。除此之外,每行都有从对象dataSet数组中呈现的名字,姓氏和年龄。我想要一种能够通过单击标题中的复选框来选择/取消选择所有行并捕获所有数据的方法。

同时,我还希望能够选择/取消选择各个行。同样,我要捕获所选每一行的数据。

以下是组件:

class Table extends React.Component {
    render() {
        return( 
            <table style={{width:"100%"}}>
              <tr>
                <th><input type="checkbox" name="name1" /></th>
                <th>Firstname</th>
                <th>Lastname</th> 
                <th>Age</th>
              </tr>
                <tbody>{this.renderRow()}</tbody>
            </table>
        );
    }

    renderRow = () => {
        const dataSet = [
            {
                FirstName: "Bob",
                LastName: "Ross",
                Age: 50
            },
            {
                FirstName: "John",
                LastName: "Doe",
                Age: 20
            },
            {
                FirstName: "Jane",
                LastName: "Doe",
                Age: 30
            }
        ];

        return dataSet.map((item) => {
            return (
                <tr>
                    <td><input type="checkbox" name="name1" /></td>
                    <td>{item.FirstName}</td>
                    <td>{item.LastName}</td>
                    <td>{item.Age}</td>
                </tr>
            )
        })
    }
};

以下是该组件的运行版本:https://codepen.io/anon/pen/exgeBg

2 个答案:

答案 0 :(得分:2)

首先,您需要为每一项赋予某种id,以便您可以将它们彼此区分开,并在映射它们时为其赋予key

const dataSet = [
    {
        id: 45612,
        FirstName: "Bob",
        LastName: "Ross",
        Age: 50
    },
    {
        id: 6542,
        FirstName: "John",
        LastName: "Doe",
        Age: 20
    },
    {
        id: 7837,
        FirstName: "Jane",
        LastName: "Doe",
        Age: 30
    }
];

添加密钥:

return (
    <tr key={item.id}>

要知道选择了哪个项目,您需要通过复选框的onClick功能发送该项目本身:

<td><input type="checkbox" name="name1" onClick={this.rowSelected(item)}/></td>

您的类中的接收函数将声明如下,可以接收该项目,然后可以接收click事件:

rowSelected = rowData => ev => {

棘手的部分现在将状态设置为包含每个选定的行。如果复选框被选中,我们将把该项目添加到先前选择的项目中,否则,我们将从数组中过滤出该项目:

rowSelected = rowData => ev => {
    this.setState(prev => ({ 
        selection:  ev.target.checked ? [...prev.selection, rowData] : prev.selection.filter(item => item.id !== rowData.id)
    }))
}

您现在可以访问this.state.selection

中的选定项目

完整代码:

class Table extends React.Component {

    rowSelected = rowData => ev => {
        this.setState(prev => ({ 
            selection:  ev.target.checked ? [...prev.selection, rowData] : prev.selection.filter(item => item.id !== rowData.id)
        }))
    }

    render() {
        return (
            <table style={{ width: "100%" }}>
                <tr>
                    <th><input type="checkbox" name="name1" /></th>
                    <th>Firstname</th>
                    <th>Lastname</th>
                    <th>Age</th>
                </tr>
                <tbody>{this.renderRow()}</tbody>
            </table>
        );
    }

    renderRow = () => {
        const dataSet = [
            {
                id: 45612,
                FirstName: "Bob",
                LastName: "Ross",
                Age: 50
            },
            {
                id: 6542,
                FirstName: "John",
                LastName: "Doe",
                Age: 20
            },
            {
                id: 7837,
                FirstName: "Jane",
                LastName: "Doe",
                Age: 30
            }
        ];

        return dataSet.map((item) => {
            return (
                <tr key={item.id}>
                    <td><input type="checkbox" name="name1" onClick={this.rowSelected(item)}/></td>
                    <td>{item.FirstName}</td>
                    <td>{item.LastName}</td>
                    <td>{item.Age}</td>
                </tr>
            )
        })
    }
};

编辑

要创建“全选”按钮,您将必须执行另一个功能:

selectAll = ev => {
    this.setState(prev => ({ selction: prev.selection.length ? [] : dataSet }))
}

如果先前选择中已经包含元素,则将其清空,如果没有任何元素,则将其替换为您的整个数据集;您将需要将其存储在其他地方,例如课外或this.dataset中。

如果您希望自动选中复选框,则需要检查对应项是否在您的状态下,以设置其checked道具(IIRC):

<input type="checkbox" name="name1" onClick={this.rowSelected(item)} checked={this.state.selection.some(slc => slc.id === item.id)}/>

答案 1 :(得分:1)

更改之处

首先,您需要保留复选框的状态,可以在代码的这一部分中设置默认值,以防您希望某些复选框开始被选中:

state = {
    header: false,
    fields: [false, false, false, false]
}

现在,当某些复选框发生更改时,您需要处理程序。
有很多方法可以做到这一点,但为简化起见,我使用了两个功能 changeCheckBoxFields可以获取要更改的复选框的索引,changeAllCheckBox可以更改标题的复选框的值,而所有其他复选框将具有与他相同的值

CodePen中运行的完整代码

完整代码:

class Table extends React.Component {
    state = {
        header: false,
        fields: [],
        dataSet: []
    }

    changeAllCheckBox = () => {
            let {
                header,
                fields,
        } = this.state
        let newHeader = !header
        let newFields = fields.map((f) => {
            return {
                checked: newHeader,
                data: f.data
            }   
        })
        this.setState({
            fields: newFields,
            header: newHeader
        })
    }

    changeCheckBoxFields = (item, index) => {
        let newState = this.state.fields
        newState[index] = {
              check: !newState[index],
              data: item
        }
        this.setState({fields: newState})
    }

    componentDidMount() {
        const dataSet = [
            {
                FirstName: "Bob",
                LastName: "Ross",
                Age: 50
            },
            {
                FirstName: "John",
                LastName: "Doe",
                Age: 20
            },
            {
                FirstName: "Jane",
                LastName: "Doe",
                Age: 30
            }
        ];
      let fields = dataSet.map((d, i) => {return {checked: false} } )
      this.setState({
            dataSet: dataSet,
            fields: fields,
      })
    }

    render() {
        return( 
            <table style={{width:"100%"}}>
              <tr>
                <th><input type="checkbox" name="name1" onChange={this.changeAllCheckBox} /></th>
                <th>Firstname</th>
                <th>Lastname</th> 
                <th>Age</th>
              </tr>
                <tbody>{this.renderRow()}</tbody>
            </table>
        );
    }

    renderRow = () => {

        return this.state.dataSet.map((item, index) => {                
            return (
                <tr key={index}>
                    <td>
                        <input type="checkbox" name="name1" onChange={() => this.changeCheckBoxFields(item, index)}  checked={this.state.fields[index].checked} />
                    </td>
                    <td>{item.FirstName}</td>
                    <td>{item.LastName}</td>
                    <td>{item.Age}</td>
                </tr>
            )
        })
    }
};

有关反应输入Reactjs Documentation

的更多信息

编辑: 仅检查完整的代码现在,您可以根据需要拥有任意多的行,可以获取数据,并且是否进行检查。组件