NEXT HMIDocs
GitHub
The editor / Actions & events

Actions & events

A property answers what a widget shows. An action answers what happens when someone presses it — write a tag, open a dialog, load a recipe, sign a user in, raise a toast. Actions are configured, not scripted, and they compose: every action's fields are ordinary properties, so any of them can be bound to live data.

Where actions live

  • On a widgetButton and Menu Toggle carry an Actions field. The list runs top to bottom on press.
  • Inside another action — an alert's OK / Cancel buttons, and the onSuccess / onFailed / onSettled handlers of the async actions below, are themselves action lists. Nesting is how a confirm-then-write flow is built.
  • On the project — the Global Events node in the editor tree runs actions at lifecycle moments rather than on a press. See Global events.

Custom widgets fire the same lists through the SDK's executeWidgetActions, so a hand-built control behaves exactly like a Button.

The action catalog

Thirteen types, in the order the Add action menu lists them.

Screens

Action Does
Open Dialog Opens a dialog from the Dialogs section, optionally passing input properties the dialog's widgets read with $componentProp.
Close Dialog Closes a named dialog, or the current one when left empty.
Open Page Overlay Opens an ordinary page as a modal on top of the current screen — reuse a full page as a popup without rebuilding it as a dialog.
Close Page Overlay Closes a named page overlay, or the current one when left empty.

Both open actions share the same presentation fields:

  • Sizeauto, small, medium, fullscreen, or fixed (then set Width / Height in pixels).
  • Placementcenter, top, bottom, left, right, or one of the trigger-anchored values (trigger-above, trigger-below, trigger-left, trigger-right) which pins the panel to the control that opened it, popover-style. Anchored placement and fullscreen are mutually exclusive.
  • Backdropdim darkens the screen behind, none leaves it untouched (right for a small anchored popover).

Page-to-page navigation is not an action. Moving between screens is the job of the navigation widgets — Navigation Menu, Tab Bar, Breadcrumb, Page Navigator — which read the page tree and stay correct as it changes. See Pages & navigation. Actions cover the things on top of a page: dialogs and overlays.

Machine

Action Does
Write Data Variable Pushes a value to a writable tag — a coil, a mode, a setpoint. Target is a datasource + path; the value is a property, so it can be a literal, another tag, or a computed $if.
Recipe: Load Downloads a saved dataset into its variables. Dataset may be fixed or bound (a row id from a $recipeList grid). Verify reads the values back after writing and fails the action if they didn't take.
Recipe: Save Captures current live values into a dataset. Leave Dataset empty to update the one that is loaded.

Session

Action Does
Login User Signs this runtime in with a Username and Password — both properties, so they come from wherever the operator typed them.
Logout User Drops back to the auto-login user.

See Users, groups & permissions for the sign-in screen around them.

Interface

Action Does
Set Language Switches the interface language by code (nl-NL). See Translations.
Set Theme Switches the active theme by id — day/night buttons, or a per-line brand. See Theming.
Show Alert A modal with a Title, Description, and two buttons whose captions you set. OK and Cancel each run their own action list, which is how you gate a dangerous write behind a confirmation. dismissible decides whether clicking away counts as cancel.
Show Toast A transient message — severity info / warning / error, discard auto (after duration, 4000 ms by default) or manual. The message is a property, so $loc and $var work in it.

Async actions and $result

Five actions cross the wire and therefore may fail: Write Data Variable, Recipe: Load, Recipe: Save, Login User, Logout User. Each carries three optional handler lists:

  • onSuccess — the server acknowledged.
  • onFailed — the server refused, or the request timed out (10 seconds) or the connection dropped.
  • onSettled — always, after whichever of the two ran.

Inside those handlers the $result source reads fields of what came back. Which fields exist depends on the action:

Action onSuccess onFailed
Login / Logout User username, groups, groupLabels reason
Write Data Variable datasource, path datasource, path, reason
Recipe: Load result, datasetId, written, total, verified, failures reason
Recipe: Save datasetId reason

onSettled sees the union of both. The reason vocabulary is fixed, so you can branch on it with $compare:

invalid_credentials · permission_denied · bad_request · bad_path · bad_field · invalid_value · opcua_unreachable · write_failed · array_index_out_of_bounds · array_state_unavailable · timeout · disconnected

A worked pattern — a Start button that confirms, writes, and tells the operator either way:

Button "Start"
└─ Show Alert   title "Start line 3?"  ok "Start"  cancel "Cancel"
   └─ onOk
      └─ Write Data Variable   LinePLC:Line3/Start = true
         ├─ onSuccess → Show Toast  "Line started"        severity info
         └─ onFailed  → Show Toast  { $result: "reason" }  severity error

No handlers means fire-and-forget. An action with all three lists empty skips the request/response round trip entirely — which is what you want for a control that writes continuously, like a slider being dragged.

Global events

Some things should happen because the system reached a state, not because someone pressed something. Select Global Events in the editor tree and attach action lists to:

Event Fires
onHmiLoaded Once, when a runtime finishes loading. The place for start-up state: pick a theme from the device, raise a "connecting" toast, open a lock-screen dialog.
onPageLoaded On the first page and on every navigation afterwards.
onUserLoggedIn When this runtime goes from the guest identity to a signed-in user.
onUserLoggedOut When it goes back to guest.
onLocaleChanged When the active language changes (not on the initial load).

They are scoped to the runtime that triggered them, so on a multi-panel installation each screen runs its own — one operator signing in on the line-side panel does not fire onUserLoggedIn in the control room.