InlineEditList

Molecule

A list whose rows edit in place: add, edit, remove and reorder, all from the keyboard, with a validation message per row and an async save state per row, drawn with the same DOM as kui-react. The server draws the list as it reads when nothing is edited; a small idempotent script (`modules/ui/InlineEditList/scripts/`, inlined once per page) keeps the state in the browser and redraws the rows. React's controlled `onChange(next, change)` and `validate` are bubbling DOM events on the root: `kui:inline-edit-change` { next, change, respond } (call `respond(promise)` to show "saving"; reject it for the row's error; the list changes only when it resolves) and `kui:inline-edit-validate` { draft, mode, items, respond } (call `respond(message | null | promise)`). `renderItem` is `itemPartial` (server-side: a row edited in the browser shows its text), `getName` is `nameKey`, `createItem` is `newItem`. `renderEditor` is not reproduced: the editor is one text input.

Synchronous

Preview
  • eu-west
  • us-east
  • ap-south
Code
<%- include('modules/ui/InlineEditList', { items: regions, messages: { label: 'Probe regions', add: 'Add region' } }) %>
<script>
  list.addEventListener('kui:inline-edit-validate', function (e) {
    e.detail.respond(isTaken(e.detail.draft) ? 'Already in the list.' : null);
  });
  list.addEventListener('kui:inline-edit-change', function (e) {
    // e.detail = { next, change: { type: 'add' | 'edit' | 'remove' | 'reorder', id, item, from?, to? } }
    save(e.detail.next);
  });
</script>

Async save (type "fail" to see an error)

Preview
  • eu-west
  • us-east
  • ap-south
Code
<script>
  list.addEventListener('kui:inline-edit-change', function (e) {
    // The row shows "Saving…" until the promise settles; a rejection becomes the row's error and the list stays as it was.
    e.detail.respond(fetch('/api/regions', { method: 'PUT', body: JSON.stringify(e.detail.next) }).then(function (r) {
      if (!r.ok) throw new Error('The server refused this value.');
    }));
  });
</script>

Read only, and capped at three

Preview
  • eu-west
  • us-east
  • ap-south
  • eu-west
  • us-east
  • ap-south
At most 3 regions.
Code
<%- include('modules/ui/InlineEditList', { items: regions, readOnly: true }) %>
<%- include('modules/ui/InlineEditList', { items: regions, maxItems: 3 }) %>
Source modules/ui/InlineEditList.ejs