React-Table添加、编辑和删除列

22

我使用Rails和React-Table来显示表格,目前它运行良好。但是如何在React-Table中添加一个编辑/删除列呢?

这是否可能?

return (
    <ReactTable
      data={this.props.working_hours}
      columns={columns}
      defaultPageSize={50}
      className="-striped -highlight"
    />
    )

你想添加新的列,以便提供编辑行数据或删除行。我说得对吗? - GAJESH PANIGRAHI
@GAJESHPANIGRAHI 你知道如何使单元格可编辑,然后添加这些按钮吗? - joy08
@vrosario 是的,请查看此链接https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/archives/v6-examples/react-table-cell-renderers - GAJESH PANIGRAHI
您可以使用https://www.npmjs.com/package/eprofit。 - xargr
3个回答

43

你需要做的就是将 columns 转化为组件状态。你可以在这个示例中看到一个工作的例子:https://codesandbox.io/s/0pp97jnrvv

[更新于 2018 年 3 月 5 日] 之前理解错了问题,这是更新后的答案:

const columns = [
    ...
    {
       Header: '',
       Cell: row => (
           <div>
               <button onClick={() => handleEdit(row.original)}>Edit</button>
               <button onClick={() => handleDelete(row.original)}>Delete</button>
           </div>
       )
    }
]

其中handleEdithandleDelete将是回调函数,您可以在这些函数中定义按钮被点击后的操作方式。


2
据我理解你的演示,你有一个显示/隐藏列的功能。但是我要求的是一个“编辑/删除行”列。 - Trinity76
1
我不得不稍微修改@Rico Chen的答案,以便将行对象传递给回调函数:Cell: ({row}) => ( - Alasdair Shields
是的,正如@AlasdairShields所说,应该是Cell: ({row}) => ( - Ayoub Laazazi

1

ReactTable v7

在表格中添加列可以通过将列对象插入到传递给useTable钩子的列定义中来实现。基本上,驻留在列定义数组中的列对象数量表示由react-table呈现的列数。

通常,最小的列对象包括Headeraccessor,其中在Header中我们传递列的名称,在accessor中,我们传递react-table将用于从传递给useTable钩子的数据中查找值的键。

{
  Header: "Column Name",
  accessor: "data key",  // can be a nested key
}

在这里,要在单元格内呈现除字符串以外的其他内容,即自定义按钮JSX,我们可以使用accessorCell选项,并将其传递给一个返回有效JSX的Function

accessor

文档中提到accessor接受stringFunction。在这里,我们使用Function来呈现JSX按钮。

accessor: String | Function(originalRow, rowIndex) => any

使用访问器选项的好处之一是rowIndex直接可用。 rowIndex表示当前由客户端管理的数据数组中行的索引号,而originalRowrow的原始对象。

在这里,rowIndex可以用作引用,以选择和修改列数据数组中的行对象。

单元格

Cell选项接受返回JSXReact.Component函数。 Cell选项通常用于格式化单元格值,但在这里我们用于呈现我们的按钮。

Cell: Function | React.Component => JSX

函数接收一个名为tableInstance的参数,该参数与使用useTable钩子的结果非常相似,但还包含了cellrowcolumn对象。

Cell: (tableInstance) => JSX

我们还可以通过解构行对象来获取行索引信息:

Cell: (tableInstance) => {
   const { row: index } = tableInstance;
   return (
      ...
   )
}

所以,取決於您的要求,決定使用 accessor 或者 Cell 來渲染編輯/添加按鈕。但如果您需要從 tableIntance 獲取更多數據/信息,那麼 Cell 是正確的選擇。
注意:如果您選擇了accessor,請確保在列屬性中包含id,因為根據文件,id 選項是必需的。

如果 accessor 是一個函數,則必須提供此選項。 此選項標識列的唯一 ID。在排序、分組、過濾等操作中,它被引用。

現在,我們已經有了。下一步是按鈕。通常按鈕是普通按鈕,可以調用處理程序來更新狀態或觸發對話框彈出窗口,或者是鏈接按鈕,可以將應用程序重定向到詳細頁面。
因此,代碼將如下所示:
    // accessor
    {
        Header: 'Action',
        id: 'action',
        accessor: (originalRow, rowIndex) => {
            return (
                // you can pass any information you need as argument
                <button onClick={() => onClickHandler(args)}>
                    X
                </button>
            )
        }
    }

    // or Cell
    {
        Header: 'Action',
        accessor: "action",
        Cell: (tableInstance) => {
            const { row: index } = tableInstance;
            return (
                // you can pass any information you need as argument
                <button onClick={() => onClickHandler(args)}>
                    X
                </button>
            )
        }
    }

例子:

const { useCallback, useEffect, useMemo, useState } = React;
const { useTable } = ReactTable;

// table data
const data = [
    {
        name: "John",
        workingHours: 40
    },
    {
        name: "Doe",
        workingHours: 40
    }
];

const AddEmployee = ({ onSubmit }) => {
    const [name, setName] = useState("");
    const [workingHours, setWorkingHours] = useState("");

    const handleSubmit = (e) => {
        onSubmit(e);
        setName("");
        setWorkingHours("");
    }

    return (
        <fieldset style={{ width: "200px" }}>
            <legend>Add Employee:</legend>
            <form onSubmit={(e) => handleSubmit(e)}>
                <input
                    type="text"
                    name="name"
                    placeholder="Name"
                    value={name}
                    onChange={(e) => setName(e.target.value)}
                />
                <br />
                <input
                    type="text"
                    name="workingHours"
                    placeholder="Working Hours"
                    value={workingHours}
                    onChange={(e) => setWorkingHours(e.target.value)}
                />
                <br />
                <button type="submit">Add</button>
            </form>
        </fieldset>
    )
}

const EditEmployee = ({ row, onSave }) => {
    const { originalRow, rowIndex } = row;
    const [name, setName] = useState(originalRow.name);
    const [workingHours, setWorkingHours] = useState(originalRow.workingHours);

    return (
        <fieldset style={{ width: "200px" }}>
            <legend>Edit Employee:</legend>
            <input
                type="text"
                name="name"
                placeholder="Name"
                value={name}
                onChange={(e) => setName(e.target.value)}
            />
            <br />
            <input
                type="text"
                name="workingHours"
                placeholder="Working Hours"
                value={workingHours}
                onChange={(e) => setWorkingHours(e.target.value)}
            />
            <br />
            <button onClick={() => onSave({ name, workingHours }, rowIndex)}>Save</button>
        </fieldset>
    )
}

function App() {
    const [tableData, setTableData] = useState(data);
    const [editingRow, setEditingRow] = useState();

    const handleDelete = useCallback((index) => {
        setTableData(tableData.filter((v, i) => i !== index));
    },[tableData]);

    const tableColumns = useMemo(() => [
        {
            Header: 'Name',
            accessor: 'name',
        },
        {
            Header: 'Working Hours',
            accessor: 'workingHours'
        },
        {
            Header: 'Action',
            id: 'action',
            accessor: (originalRow, rowIndex) => {
                return (
                    <div>
                        <button onClick={() => setEditingRow({ originalRow, rowIndex })}>
                            Edit
                        </button>
                        <button onClick={() => handleDelete(rowIndex)}>
                            Delete
                        </button>
                    </div>   
                )
            }
        }
    ], [handleDelete]);

    const {
        getTableProps,
        getTableBodyProps,
        headerGroups,
        rows,
        prepareRow
    } = useTable({
        columns: tableColumns,
        data: tableData,
    });

    const handleSubmit = (event) => {
        event.preventDefault();
        const formData = new FormData(event.currentTarget);
        const newData = {};
        formData.forEach((value, key) => newData[key] = value);
        setTableData((prevData) => {
            return [...prevData, newData];
        });
    };

    const handleEdit = useCallback((row, rowIndex) => {
        const editedData = tableData.map((rowData, index) => {
            if (index === rowIndex) {
               return row;
            }
            return rowData;
        });
        setTableData(editedData);
        setEditingRow();
    },[tableData])

    return (
        <div>
            <h3>React-table v.7</h3>
            <br />
            { editingRow ? <EditEmployee row={editingRow} onSave={handleEdit} /> : <AddEmployee onSubmit={handleSubmit} /> }
            <table {...getTableProps()}>
                <thead>
                    {headerGroups.map(headerGroup => (
                        <tr {...headerGroup.getHeaderGroupProps()}>
                            {headerGroup.headers.map(column => (
                                <th {...column.getHeaderProps()}> 
                                    {column.render('Header')}
                                </th>
                            ))}
                    </tr>
                    ))}
                </thead>
                <tbody {...getTableBodyProps()}>
                    {rows.map((row, i) => {
                        prepareRow(row)
                        return (
                            <tr {...row.getRowProps()}>
                                {row.cells.map(cell => {
                                    return (
                                        <td {...cell.getCellProps()}> 
                                            {cell.render('Cell')}
                                        </td>
                                    )
                                })}
                            </tr>
                        )
                    })}
                </tbody>
            </table>
        </div>
    )
}
 
ReactDOM.render(<App />, document.querySelector('.react'));
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/react-table@7.8.0/dist/react-table.development.js"></script>

<div class='react'></div>


0
你可以使用React-table中列的访问器属性来添加按钮。这是代码示例:
     {
        Header: 'Action',
        accessor: (originalRow, rowIndex) => (
           <div>
               <button onClick={() => handleEdit(originalRow)}>Edit</button>
               <button onClick={() => handleDelete(originalRow)}>Delete</button>
           </div>
        ),
        id: 'action',
      },

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接