单击具有反应的单元格上的 "Edit" 按钮时如何使行 editable-table
How to make the row editable when clicking on an "Edit" button on a cell with react-table
我正在我的应用程序上使用 react-table
制作交互式 table。
我的目标是制作一个 table,当单击 table 单元格中的按钮时,每行可以编辑 table。
我设计了一个 EditableCell
如下所示。
import React, {useState} from "react";
export const EditableCell = ({
value: initialValue,
row: Row,
column: {id, editable, state},
isEditing,
updateItem, // This is a custom function that we supplied to our table instance
}) => {
// We need to keep and update the state of the cell normally
const [value, setValue] = React.useState(initialValue);
const {index} = Row;
const onChange = e => {
setValue(e.target.value);
};
// We'll only update the external data when the input is blurred
const onBlur = () => {
updateItem(index, id, value);
}
// If the initialValue is changed external, sync it up with our state
React.useEffect(() => {
setValue(initialValue)
}, [initialValue]);
/**
* Event handler to make a row editable.
* @param e
*/
const setRowEditing = (e) => {
// TODO
};
let retObj = null;
if (isEditing && editable) {
switch (id) {
default:
retObj = <input className="input-edit w-100" value={value} onChange={onChange} onBlur={onBlur}/>;
break;
}
} else {
switch (id) {
case 'action_btn':
retObj = <>
<button className="btn btn-sm btn-info btn-sm-td" onClick={setRowEditing}>{ isEditing? "Save" : "Edit"}</button>
</>;
break;
default:
retObj = <div>{value}</div>;
break;
}
}
return retObj;
}
export const defaultColumn = {
Cell: EditableCell,
};
而我的 table 的定义是:(我使用了我的 EditableCell 组件)
export default function Table({ columns, data, updateItem }) {
// Use the useTable Hook to send the columns and data to build the table
const {
getTableProps, // table props from react-table
getTableBodyProps, // table body props from react-table
headerGroups, // headerGroups, if your table has groupings
rows, // rows for the table based on the data passed
prepareRow // Prepare the row (this function needs to be called for each row before getting the row props)
} = useTable({
columns,
data,
defaultColumn,
updateItem,
}, useBlockLayout, useRowState);
/*
Render the UI for your table
- react-table doesn't have UI, it's headless. We just need to put the react-table props from the Hooks, and it will do its magic automatically
*/
return (
<table className="data-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>
);
};
在 setRowEditing
函数中,我将更改当前行或其单元格的状态,以便该行中的单元格呈现为输入字段或其他内容。
但是我不知道如何正确地改变状态。
你能就此提出建议吗?
在您传递给 React 的列数组中 table 您需要创建一个按钮,该按钮的 onClick 函数需要一个回调来编辑您的数据以添加一个 isEditing: true
因此您将处理从 table 外部将行转换为编辑模式。 editable 单元格中不需要 setRowEditing
。
函数设置 table 数据 'isEditing' 属性
const handleClickEditRow = (rowIndex) => {
setTableData(prev => prev.map((r, index) => ({...r, isEditing: rowIndex === index})))
}
在您的专栏中
{
accessor: '[editButton]',
Cell: (cellObj) => <button onClick={() => handleClickEditRow(cellObj.row.index)}>Edit</button>
}
我试图通过执行以下步骤实现此 feature/functionality:
// leverage useState react hook.
const [editableRowIndex, setEditableRowIndex] = React.useState(null);
状态变量的初始值为空 - 因此所有行都不会打开进行编辑。
将状态变量和方法传递给 useTable() 根挂钩。
自定义插件挂钩和其他 variables/methods 维护组件状态从 table 实例返回。这些您以后可以从任何地方检索。
您可以根据状态变量渲染 Editable 单元格组件和自定义插件挂钩(在本例中为编辑挂钩)。
const {
// all your hooks...
} = useTable(
{
columns,
data,
// all your other hooks...
updateMyData,
**// pass state variables so that we can access them in edit hook later
editableRowIndex, // index of the single row we want to edit
setEditableRowIndex // setState hook for toggling edit on/off switch**
},
// other hooks...
(hooks) => {
hooks.allColumns.push((columns) => [
// other hooks such as selection hook
...columns,
// edit hook
{
accessor: "edit",
id: "edit",
Header: "edit",
Cell: **({ row, setEditableRowIndex, editableRowIndex })** => (
<button
className="action-button"
onClick={() => {
**const currentIndex = row.index;
if (editableRowIndex !== currentIndex) {
// row requested for edit access
setEditableRowIndex(currentIndex);
} else {
// request for saving the updated row
setEditableRowIndex(null); // keep the row closed for edit after we finish updating it
const updatedRow = row.values;
console.log("updated row values:");
console.log(updatedRow);
// call your updateRow API
}**
}}
>
*{/* single action button supporting 2 modes */}*
**{editableRowIndex !== row.index ? "Edit" : "Save"}**
</button>
)
}
]);
}
);
示例可在以下 link 中找到:
代码沙箱link:
https://codesandbox.io/s/github/smmziaul/only-one-row-editable
github 回购 link:
https://github.com/smmziaul/only-one-row-editable
我正在我的应用程序上使用 react-table
制作交互式 table。
我的目标是制作一个 table,当单击 table 单元格中的按钮时,每行可以编辑 table。
我设计了一个 EditableCell
如下所示。
import React, {useState} from "react";
export const EditableCell = ({
value: initialValue,
row: Row,
column: {id, editable, state},
isEditing,
updateItem, // This is a custom function that we supplied to our table instance
}) => {
// We need to keep and update the state of the cell normally
const [value, setValue] = React.useState(initialValue);
const {index} = Row;
const onChange = e => {
setValue(e.target.value);
};
// We'll only update the external data when the input is blurred
const onBlur = () => {
updateItem(index, id, value);
}
// If the initialValue is changed external, sync it up with our state
React.useEffect(() => {
setValue(initialValue)
}, [initialValue]);
/**
* Event handler to make a row editable.
* @param e
*/
const setRowEditing = (e) => {
// TODO
};
let retObj = null;
if (isEditing && editable) {
switch (id) {
default:
retObj = <input className="input-edit w-100" value={value} onChange={onChange} onBlur={onBlur}/>;
break;
}
} else {
switch (id) {
case 'action_btn':
retObj = <>
<button className="btn btn-sm btn-info btn-sm-td" onClick={setRowEditing}>{ isEditing? "Save" : "Edit"}</button>
</>;
break;
default:
retObj = <div>{value}</div>;
break;
}
}
return retObj;
}
export const defaultColumn = {
Cell: EditableCell,
};
而我的 table 的定义是:(我使用了我的 EditableCell 组件)
export default function Table({ columns, data, updateItem }) {
// Use the useTable Hook to send the columns and data to build the table
const {
getTableProps, // table props from react-table
getTableBodyProps, // table body props from react-table
headerGroups, // headerGroups, if your table has groupings
rows, // rows for the table based on the data passed
prepareRow // Prepare the row (this function needs to be called for each row before getting the row props)
} = useTable({
columns,
data,
defaultColumn,
updateItem,
}, useBlockLayout, useRowState);
/*
Render the UI for your table
- react-table doesn't have UI, it's headless. We just need to put the react-table props from the Hooks, and it will do its magic automatically
*/
return (
<table className="data-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>
);
};
在 setRowEditing
函数中,我将更改当前行或其单元格的状态,以便该行中的单元格呈现为输入字段或其他内容。
但是我不知道如何正确地改变状态。
你能就此提出建议吗?
在您传递给 React 的列数组中 table 您需要创建一个按钮,该按钮的 onClick 函数需要一个回调来编辑您的数据以添加一个 isEditing: true
因此您将处理从 table 外部将行转换为编辑模式。 editable 单元格中不需要 setRowEditing
。
函数设置 table 数据 'isEditing' 属性
const handleClickEditRow = (rowIndex) => {
setTableData(prev => prev.map((r, index) => ({...r, isEditing: rowIndex === index})))
}
在您的专栏中
{
accessor: '[editButton]',
Cell: (cellObj) => <button onClick={() => handleClickEditRow(cellObj.row.index)}>Edit</button>
}
我试图通过执行以下步骤实现此 feature/functionality:
// leverage useState react hook.
const [editableRowIndex, setEditableRowIndex] = React.useState(null);
状态变量的初始值为空 - 因此所有行都不会打开进行编辑。
将状态变量和方法传递给 useTable() 根挂钩。 自定义插件挂钩和其他 variables/methods 维护组件状态从 table 实例返回。这些您以后可以从任何地方检索。
您可以根据状态变量渲染 Editable 单元格组件和自定义插件挂钩(在本例中为编辑挂钩)。
const {
// all your hooks...
} = useTable(
{
columns,
data,
// all your other hooks...
updateMyData,
**// pass state variables so that we can access them in edit hook later
editableRowIndex, // index of the single row we want to edit
setEditableRowIndex // setState hook for toggling edit on/off switch**
},
// other hooks...
(hooks) => {
hooks.allColumns.push((columns) => [
// other hooks such as selection hook
...columns,
// edit hook
{
accessor: "edit",
id: "edit",
Header: "edit",
Cell: **({ row, setEditableRowIndex, editableRowIndex })** => (
<button
className="action-button"
onClick={() => {
**const currentIndex = row.index;
if (editableRowIndex !== currentIndex) {
// row requested for edit access
setEditableRowIndex(currentIndex);
} else {
// request for saving the updated row
setEditableRowIndex(null); // keep the row closed for edit after we finish updating it
const updatedRow = row.values;
console.log("updated row values:");
console.log(updatedRow);
// call your updateRow API
}**
}}
>
*{/* single action button supporting 2 modes */}*
**{editableRowIndex !== row.index ? "Edit" : "Save"}**
</button>
)
}
]);
}
);
示例可在以下 link 中找到:
代码沙箱link: https://codesandbox.io/s/github/smmziaul/only-one-row-editable
github 回购 link: https://github.com/smmziaul/only-one-row-editable