Chapter 31 of 34

Inline editing

Change quantity and status right in the table – and recalculate what depends on them.

  • ⏱ 6 min
  • ▶ Video episode 031
  • git tag ep-031
  • needs @guiexpert/table@1.1.89

After this chapter you can

  • make a column editable
  • convert input with editInputPipe
  • use a select editor
  • react to changes

Make columns editable

Editing is switched on per column. Three fields of the ColumnDefIf matter:

src/model/order-editing.ts
import { type ColumnDefIf, SelectCellRenderer, TrueFn, ValueLabel, editInputPipeForNumber } from "@guiexpert/table";
import type { Order } from "./data/orders";
export function applyOrderEditing(columns: ColumnDefIf[]): void {
const column = (property: keyof Order) => columns.find(c => c.property === property)!;
const quantity = column("quantity");
quantity.editable = TrueFn;
quantity.editInputPipe = editInputPipeForNumber; // the input text becomes a number
const status = column("status");
status.editable = TrueFn;
status.getEditRenderer = () => new SelectCellRenderer( // a <select> instead of a text input
["open", "paid", "shipped", "cancelled"].map(s => new ValueLabel(s, s)));
}
/** After an edit: recalculate the derived value. */
export function recalcOrder(order: Order): void {
order.total = Math.round(order.quantity * order.price * 100) / 100;
}

Start editing: double-click a cell, or press F2 on the focused cell. The value is taken over when the editor fires its change event – Enter or leaving the field for a text input, picking an option for a select.

After the edit

The table writes the new value into your object (via AreaModelIf.setValue()) and reports it: EventListenerIf.onModelChanged() with a GeModelChangeEvent. Derived values are your job:

import { EventAdapter, type GeModelChangeEvent } from "@guiexpert/table";
class EditEvents extends EventAdapter {
constructor(private readonly onEdited: (rowIndex: number, columnIndex: number) => void) {
super();
}
override onModelChanged(evt: GeModelChangeEvent): void { // after every edit
for (const cell of evt.cells) this.onEdited(cell.rowIndex, cell.columnIndex);
}
}
const events = new EditEvents((row, col) => {
const order = tableModel.getBodyModel().getRowByIndex(row) as Order;
recalcOrder(order); // total = quantity × price
(tableModel.getAreaModel("footer") as OrderTotalsFooterModel).invalidate(); // footer: sum again
tableApi.repaint();
});
const tableScope = new TableScope(host, tableModel, new SimpleDomService(), options, events);
tableScope.firstInit();
const tableApi = tableScope.getApi();
Live Edit quantity and status
Screenshot: Edit quantity and status Screenshot: Edit quantity and status
Double-click a quantity, type 20, press Enter: total and footer update. Double-click a status: a select box.

Saving

The table has no notion of a backend. Send the change from onModelChanged – the event contains row and column, the new value is already in your object – and, if the server rejects it, write the old value back and repaint.

Next

Not the user changes the values, the market does: chapter 32 (Live data).

API used in this chapter