Skip to content
SumOfficeSumOfficeSumOffice

Integration recipes

Responding to a click and double-click, a context menu for a table cell, running an external command, and a full transport-system scenario from event to DOCX.

How to respond to a click and double-click

Section titled “How to respond to a click and double-click”
editor.interactions.on("elementActivated", async (event) => {
const { gesture, target } = event;
if (gesture === "click" && target.kind === "comment") {
hostSidebar.openComment(target.nodeId);
}
if (gesture === "doubleClick" &&
target.hostData?.type === "shipment") {
await hostApp.openShipment(target.hostData.id);
}
});
editor.contextMenu.registerProvider("transport-suite", async (ctx) => {
if (ctx.target.kind !== "tableCell") return [];
return [
{ id: "transport.openCargo", label: "Open cargo card",
enabled: Boolean(ctx.target.hostData?.id) },
{ id: "transport.bindRoute", label: "Bind to route",
enabled: !ctx.readOnly },
{ type: "separator" },
{ id: "a4.table.insertRowBelow", label: "Insert row below",
command: { type: "insert_table_row", position: "below" } }
];
});
editor.commands.register("transport.bindRoute", async (ctx) => {
const route = await hostUi.chooseRoute();
if (!route) return;
return ctx.session.execute({
operationId: crypto.randomUUID(),
expectedRevision: ctx.revision,
target: ctx.target,
command: { type: "replace_target_text", text: route.displayName }
});
});

Transport-system scenario from event to DOCX

Section titled “Transport-system scenario from event to DOCX”

Step by step: a right-click on a cargo row

Section titled “Step by step: a right-click on a cargo row”
  • The user right-clicks. The surface translates the click coordinates into document page coordinates and asks the core what was hit.

  • The core answers what’s under the pointer. For example, a table cell: its stable identifier, row and column numbers, enclosing elements, and the revision number in which all this is valid.

  • The editor asks your menu item providers, passing them this context — and only this context, not a reference to a markup element.

  • Your provider adds its own actions. “Open cargo card” and “Bind to route” appear alongside the permitted built-in items.

  • The user picks a route. Your interface returns its identifier; the command to change the document is assembled separately — the choice in your system and the edit in the document stay separate actions.

  • The core accepts the command or refuses it. The expected revision and the list of allowed actions prevent an edit from being applied to a stale document or to an object it wasn’t meant for.

  • The surface updates. The contentChanged and commandStateChanged events bring the new revision number, and only the affected pages are redrawn, not the whole document.

  • Saving and reopening confirm the result. The document is saved as a separate file or published all at once, then read back — this verifies that what landed on disk is exactly what the user saw.

{
"schema": "a4.interaction-context.v1",
"gesture": "contextMenu",
"revision": 42,
"readOnly": false,
"target": {
"kind": "tableCell",
"nodeId": "body.block[18].row[2].cell[1]",
"ancestors": [{"kind":"table","nodeId":"body.block[18]"}],
"capabilities": ["read","editText","insertRow"],
"hostData": {"type":"shipment","id":"SHP-009173"}
},
"hit": {"pageIndex":3,"xMilliPx":412000,"yMilliPx":286000}
}
{
"ok": false,
"error": {
"code": "revision_conflict",
"expectedRevision": 42,
"actualRevision": 43,
"retry": "refresh_target_and_command_state"
}
}

Documentation assistant

Answers are assembled from the documentation and may be inaccurate — check the sources.