Although the FlexGrid control provides efficient, Excel-style editing by default, you may want to customize the editing behavior. If for some reason you don't like the Excel-style editing and prefer to add editing buttons to every row (typical of editable HTML tables), you can accomplish that using the formatItem event and a little code.
Learn about FlexGrid | FlexGrid API Reference
This example uses React.
import 'bootstrap.css';
import '@mescius/wijmo.styles/wijmo.css';
import ReactDOM from 'react-dom/client';
import React, { useRef } from 'react';
import useEvent from 'react-use-event-hook';
import * as wjGrid from '@mescius/wijmo.react.grid';
import * as wjcCore from '@mescius/wijmo';
import './app.css';
import { data } from './data';
function App() {
const flexRef = useRef();
const currentEditItemRef = useRef();
const initializeGrid = useEvent((flex) => {
flexRef.current = flex;
flex.rows.defaultSize = 40;
// custom formatter to paint buttons and editors
flex.formatItem.addHandler((s, e) => {
var _a, _b;
if (e.panel == s.cells) {
let col = s.columns[e.col], item = s.rows[e.row].dataItem;
if (item == currentEditItemRef.current) {
// create editors and buttons for the item being edited
switch (col.binding) {
case 'buttons':
e.cell.innerHTML = (_a = document.getElementById('tplBtnEditMode')) === null || _a === void 0 ? void 0 : _a.innerHTML;
e.cell['dataItem'] = item;
break;
case 'country':
case 'sales':
case 'expenses':
e.cell.innerHTML = '<input class="form-control" ' +
'id="' + col.binding + '" ' +
'value="' + s.getCellData(e.row, e.col, true) + '"/>';
break;
}
}
else {
// create buttons for items not being edited
switch (col.binding) {
case 'buttons':
e.cell.innerHTML = (_b = document.getElementById('tplBtnViewMode')) === null || _b === void 0 ? void 0 : _b.innerHTML;
e.cell['dataItem'] = item;
break;
}
}
}
});
// handle button clicks
flex.addEventListener(flex.hostElement, 'click', (e) => {
const target = e.target;
const button = target instanceof HTMLButtonElement ? target : target.parentElement;
if (button instanceof HTMLButtonElement) {
// get button's data item
let item = wjcCore.closest(button, '.wj-cell')['dataItem'];
// handle buttons
switch (button.id) {
// start editing this item
case 'btnEdit':
editItem(item);
break;
// remove this item from the collection
case 'btnDelete':
(flex.collectionView).remove(item);
break;
// commit edits
case 'btnOK':
commitEdit();
break;
// cancel edits
case 'btnCancel':
cancelEdit();
break;
}
}
});
// exit edit mode when scrolling the grid or losing focus
flex.scrollPositionChanged.addHandler(cancelEdit);
flex.lostFocus.addHandler(cancelEdit);
});
const editItem = useEvent((item) => {
cancelEdit();
currentEditItemRef.current = item;
flexRef.current.invalidate();
});
const commitEdit = useEvent(() => {
if (currentEditItemRef.current) {
flexRef.current.columns.forEach((col) => {
let input = flexRef.current.hostElement.querySelector('#' + col.binding);
if (input) {
let value = wjcCore.changeType(input.value, col.dataType, col.format);
if (wjcCore.getType(value) == col.dataType) {
currentEditItemRef.current[col.binding] = value;
}
}
});
}
currentEditItemRef.current = null;
flexRef.current.invalidate();
});
const cancelEdit = useEvent(() => {
if (currentEditItemRef.current) {
currentEditItemRef.current = null;
flexRef.current.invalidate();
}
});
return (<div className="container-fluid">
<wjGrid.FlexGrid isReadOnly={true} selectionMode="None" headersVisibility="Column" initialized={initializeGrid} itemsSource={data}>
<wjGrid.FlexGridColumn binding="id" header="ID" width={50}/>
<wjGrid.FlexGridColumn binding="country" header="Country" isRequired={true}/>
<wjGrid.FlexGridColumn binding="sales" header="Sales" format="n2"/>
<wjGrid.FlexGridColumn binding="expenses" header="Expenses" format="n2"/>
<wjGrid.FlexGridColumn binding="buttons" header="Edit" width={160}/>
</wjGrid.FlexGrid>
<div id="tplBtnViewMode">
<button id="btnEdit" className="btn btn-default btn-sm">
<span className="glyphicon glyphicon-pencil"></span> Edit
</button>
<button id="btnDelete" className="btn btn-default btn-sm">
<span className="glyphicon glyphicon-remove"></span> Delete
</button>
</div>
<div id="tplBtnEditMode">
<button id="btnOK" className="btn btn-primary btn-sm">
<span className="glyphicon glyphicon-ok"></span> OK
</button>
<button id="btnCancel" className="btn btn-warning btn-sm">
<span className="glyphicon glyphicon-ban-circle"></span> Cancel
</button>
</div>
</div>);
}
const container = document.getElementById('app');
if (container) {
const root = ReactDOM.createRoot(container);
root.render(<App />);
}
Submit and view feedback for