Turn an AntV S2 Data Table into an Editable Spreadsheet with React
This tutorial shows how to convert a read‑only AntV S2 data table into an interactive, editable spreadsheet by adding a controlled input element, handling cell click events, synchronizing edits back to the data set, and keeping the editor in sync with scrolling and focus.
In this guide we demonstrate how to make an AntV S2 data‑display table editable using React. First, we set up a basic S2 table by importing the necessary packages and rendering <SheetComponent> with a simple data configuration.
1. Create a controlled input element
<input value={value} onChange={e => setValue(e.target.value)} />This input will later be positioned over a cell.
2. Register a DATA_CELL_CLICK event
S2Ref.current.on(S2Event.DATA_CELL_CLICK, e => {
// Save the clicked cell
setCell(e.target.cfg.parent);
});Saving the cell information allows us to place the editor precisely.
3. Overlay the input on the clicked cell
useEffect(() => {
const spreadsheet = S2Ref.current;
if (spreadsheet && cell) {
const cellMeta = pick(cell.getMeta(), ['x','y','width','height','fieldValue']);
cellMeta.x -= scroll.scrollX || 0;
cellMeta.y -= (scroll.scrollY || 0) - (spreadsheet.getColumnNodes()[0] || {height:0}).height;
setPosition({ left: cellMeta.x, top: cellMeta.y, width: cellMeta.width, height: cellMeta.height });
setShow(true);
setValue(cellMeta.fieldValue);
}
}, [cell]);When show becomes true we also focus the input automatically.
4. Save changes
4.1 Save function
const onSave = (inputVal) => {
const spreadsheet = S2Ref.current;
if (spreadsheet && cell) {
const { rowIndex, valueField } = cell.getMeta();
spreadsheet.dataSet.originData[rowIndex][valueField] = inputVal;
spreadsheet.render(true);
setShow(false);
}
};4.2 Trigger on Enter
useEffect(() => {
const onKeyDown = e => {
if (e.keyCode === 13) {
e.preventDefault();
onSave(value);
}
};
if (inputRef.current) {
inputRef.current.addEventListener('keydown', onKeyDown);
}
return () => {
inputRef.current?.removeEventListener('keydown', onKeyDown);
};
}, [value]);5. Save before switching cells
useEffect(() => {
const spreadsheet = S2Ref.current;
const handleClick = e => {
onSave(value);
setCell(e.target.cfg.parent);
};
if (spreadsheet) {
spreadsheet.on(S2Event.DATA_CELL_CLICK, handleClick);
}
return () => {
spreadsheet?.off(S2Event.DATA_CELL_CLICK, handleClick);
};
}, [value]);6. Keep the editor in sync with scrolling
useEffect(() => {
const spreadsheet = S2Ref.current;
const handleScroll = () => {
if (spreadsheet) {
const newScroll = spreadsheet.facet.getScrollOffset();
if (!isEqual(newScroll, scroll)) {
setScroll(newScroll);
}
}
};
if (spreadsheet) {
spreadsheet.on(S2Event.LAYOUT_CELL_SCROLL, handleScroll);
}
return () => {
spreadsheet?.off(S2Event.LAYOUT_CELL_SCROLL, handleScroll);
};
}, []);
useEffect(() => {
const spreadsheet = S2Ref.current;
if (spreadsheet && cell) {
const cellMeta = pick(cell.getMeta(), ['x','y','width','height','fieldValue']);
cellMeta.x -= scroll.scrollX || 0;
cellMeta.y -= (scroll.scrollY || 0) - (spreadsheet.getColumnNodes()[0] || {height:0}).height;
setPosition({ left: cellMeta.x, top: cellMeta.y, width: cellMeta.width, height: cellMeta.height });
}
}, [scroll]);After implementing these steps, the S2 table behaves like an editable spreadsheet, supporting inline editing, keyboard saving, focus management, and scroll synchronization.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Alipay Experience Technology
Exploring ultimate user experience and best engineering practices
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
