Skip to main content
Version: 1.0.8

Tutorial: Build a Dashboard

Build a line-overview screen: live values, state-coloured equipment, a trend, an alarm banner and drill-down to detail.

You will need: tags with live data (Connect a device) and history enabled on at least one analogue tag. Time: ~30 minutes.


Step 1 — Create the view​

In the Designer's Project Browser, click Create View (the + on Views), or right-click the Views folder and choose New View.

FieldValue
TitleLine 1 Overview
Slugline1-overview
TypeFlex Layout (Responsive)

Flex because a dashboard should survive being opened on a display size you did not anticipate. Use coordinate for a mimic where position carries meaning — that is a different screen.

→ Layout modes


Step 2 — Add the alarm banner​

Drag an AlarmBell into the top-right corner. It needs no binding — it reads the alarm system directly.

PropertyValue
countModeunacked
colorByPriorityon
pulseOnNewon

Counting unacknowledged rather than all active means the badge reflects work outstanding, not just conditions present.


Step 3 — Add a KPI row​

Drop a FlexContainer across the top and put three Text widgets inside it.

Bind each to a tag. On the speed display, add a Number Format transform (#,##0) — or better, set a format string on the tag so every screen inherits it.

→ Property bindings


Step 4 — Add a gauge with state colour​

Drag a Gauge and bind:

PropertyBinding
valuetag Site1/Line1/Filler/Motor1/Speed
min / max0 / 3000
gaugeColortag …/Speed → Map transform

In the Map transform, set Match input by to Numeric range and Produce output as to Color:

[,2400) → #16a34a normal
[2400,2800] → #f59e0b high
(2800,] → #dc2626 too high
fallback → #6b7280

(For fixed bands drawn on the dial itself, the Gauge's colorRanges property does the same job without a binding.)

The colour is now doing the reading for the operator. That is the point of a dashboard.


Step 5 — Add a running indicator​

Drag an Icon and bind color to …/Running with a Map transform (Exact value → Color):

InputOutput typeOutput
truecolor#16a34a
falsecolor#6b7280
fallbackcolor#6b7280
Give bad quality its own appearance

A grey icon meaning "stopped" and a grey icon meaning "we have no idea" is the failure operators remember. Add a distinct bad-quality appearance, or a small quality indicator beside it.


Step 6 — Add a trend​

Drag a Historian chart below the KPI row.

PropertyValue
seriesTwo entries, tagPath …/Speed and …/Current
timeWindowSec3600 (last hour)
aggregateavg

The chart reads the historian directly. If it is empty, history is not enabled on those tags. → Historian configuration

Use minmax instead of avg when spikes are the reason you are looking — averaging a 200 ms current spike into a one-minute bucket erases it. For a single tag in a compact tile, the HMI Trend widget (HmiTrendChart) draws one tag's trailing window with its alarm limits.


Step 7 — Add drill-down​

Drop a Button labelled "Motor detail". Right-click it, choose Edit Events, select Click and add a Navigate action:

Navigate → Switch to view: "motor-detail"
params: { tagPath: "Site1/Line1/Filler/Motor1" }

Then build motor-detail once, parameterised by tagPath. Every motor on the site uses that one view.

→ Event actions · Embedded views


Step 8 — Add an operator control​

Drag a Slider and bind value to …/SpeedSetpoint. Bound to a writable tag, an input widget reads and writes it.

Two things to get right:

  1. Set a write level on the tag. A setpoint that changes production should require at least Operate, and often Supervise.
  2. Confirm consequential writes. Tick Require confirmation before writing on the Set tag action and give it a message, rather than writing on every drag. Confirmation is an option on the action, not something a script asks for.
Slider.change → Set tag Site1/Line1/Filler/Motor1/SpeedSetpoint = {{value}}
with confirmation: "Set the filler speed?"

If you need to do more than write — validate a range, then write, then say so — use a Run script action and raise the toast yourself:

const rpm = Number(context.self.props.value);
if (!Number.isFinite(rpm) || rpm > 3000) {
context.ui.notify({ message: "Speed must be at most 3000 RPM", severity: "error" });
return;
}
await system.tag.write("Site1/Line1/Filler/Motor1/SpeedSetpoint", rpm);
context.ui.notify({ message: "Setpoint applied", severity: "success" });

→ Tag write security


Step 9 — Publish and check as an operator​

Save, then open http://localhost:8182/{project}.

You are seeing what an operator sees. Check it on the actual panel hardware — a screen that is comfortable on a laptop can be unreadable on a 10" panel in a bright room.

Fields, buttons and menus draw at the project's Control size (Project settings → Theme), SM by default — sized for a desktop. For a touch panel set it to MD or larger. → Control size


Step 10 — Review​

  • Abnormal state is obvious without reading numbers
  • Bad quality looks different from a normal value
  • Colour is not the only signal for anything safety-relevant
  • Text is legible at the real viewing distance
  • Touch targets work with gloves (Control size MD or larger on a touch panel)
  • Detail views are parameterised, not duplicated
  • Writes are confirmed and write-level gated
  • The screen opens quickly on the target hardware

Next​

NextWhy
Alarm on a tagMake the banner mean something
LiveView authenticationRequire an operator login
ComponentsThe full widget reference