1. Overview
WinCC Unified (TIA Portal V17/V18/V19) supports two fundamentally different script execution models: event-based scripts (Loaded, Cleared, Click left, Click right) attached to a screen object, and dynamization scripts bound to a tag whose value change automatically re-evaluates the script. The second model is the correct mechanism when an HMI must react in real time to a PLC tag edge — for example, latching an alarm, displaying a pop-up window the moment a discrete bit goes high, or surfacing a maintenance request on the operator panel without the operator having to navigate or click.
The reason this distinction matters is execution timing. A script wired to the Loaded event of a screen only fires when that screen is instantiated by the runtime. It does not re-fire when a tag changes value while the screen is already on display. A dynamization script, in contrast, executes every time the configured quality of the trigger tag changes (value, quality code, or timestamp), regardless of screen state, as long as the host element is in the active screen tree.
This article documents the production-grade approach to displaying a pop-up window in response to a real-time tag change: selecting the trigger tag, choosing a stable host element, writing the dynamization JavaScript, calling UI.OpenScreenInPopup or Screen.OpenPopup depending on the project schema, and verifying behavior in Runtime.
2. Prerequisites
Before configuring, verify the following in TIA Portal:
- TIA Portal V17 or later with WinCC Unified Comfort/ES installed. Earlier Comfort Panel firmware (V16) supports VBScript only — see Section 10 for migration notes.
- HMI device with WinCC Unified Runtime (Comfort Panel V18 firmware, Unified PC Runtime, or Unified Comfort Panel). The script engine is Chromium-based V8 in Unified and is not interchangeable with legacy WinCC flexible / TIA WinCC Comfort VBScript.
- PLC tag exposed to the HMI via the standard HMI tag table or an S7 connection. The tag must have a configured acquisition cycle (default 1 s) or a configured trigger for sub-second response.
-
Pop-up screen already authored in the project tree (Screens → Add new screen → Screen type: Pop-up or a regular screen invoked via
OpenScreenInPopup). - Always-available host element present in the active screen window. See Section 4.
3. Event Scripts vs. Dynamization Scripts
WinCC Unified exposes two script binding models in the screen editor's Properties pane. The model you choose dictates when the script runs.
| Binding | Trigger condition | Typical use | Re-fires while screen open? |
|---|---|---|---|
| Event: Loaded | Screen or object instantiated | Initial values, one-shot setup | No |
| Event: Cleared | Screen or object removed from memory | Cleanup, release handles | No |
| Event: Click left | Mouse/touch press on the element | Button logic | Operator-driven |
| Event: Click right | Right mouse press | Context menus | Rarely used on panels |
| Dynamization: Script (Tag trigger) | Trigger tag value/quality changes | Alarm-driven pop-ups, status mirror | Yes |
When the goal is "show a pop-up the instant a tag changes", the dynamization binding is the only correct choice. Event scripts on Loaded/Cleared will appear to work in testing only because the user is launching the screen containing the pop-up, masking the design error.
4. Screen & Script Placement Strategy
Because the dynamization script must run against a live, rendered object, the host element must satisfy three conditions:
- Persistent visibility: The object must be inside a screen window that is part of the permanently visible shell. On Unified PC and Comfort Panels, the start screen is always part of the active tree. On projects using a main screen window for global navigation, place the host in that window, not inside a sub-page that may be closed.
- Invisibility to the operator: Use a zero-size, zero-opacity, or off-screen element. Field-tested candidates: a 1×1 pixel rectangle, a transparent text field, or an object positioned at coordinates (–1000, –1000). The object is purely a script carrier.
- Non-interactive: Disable the Operator input permission to prevent accidental focus changes during alarm display.
5. Step-by-Step: Configure the Trigger Tag
- In the project tree, expand HMI Tags and double-click the tag table that owns your trigger (e.g., Default tag table).
- Locate the discrete tag that will fire the pop-up. Confirm the connection (S7-1500 to Unified, S7-1200 to Comfort Panel, or OPC UA).
- Set Acquisition mode to Cyclical continuous with a 100 ms cycle for fast edge detection, or configure a single-step trigger in the PLC to set the bit only for one scan and rely on edge detection in the script.
- Optionally, mark the tag with a unique name such as
HMI_AlarmRequest_Bit00so the script binding is identifiable in the engineering view.
6. Step-by-Step: Create the Dynamization Script
- Open the start screen (or main screen window) in the screen editor.
- Insert a small invisible object: from the toolbox, drag a Rectangle onto the canvas, set Width = 1, Height = 1, X = –1000, Y = –1000, Background = transparent.
- Select the rectangle. In the Properties pane, scroll to Dynamizations and click the Script entry.
- Click the name field and create a new script named
TagChange_ShowAlarmPopup. - In the script editor, set the Trigger tag property to your alarm tag (e.g.,
HMI_AlarmRequest_Bit00). - Set Trigger quality = On value change (default) for edge-sensitive behavior, or On any change if you also need to react to quality-code drops.
- Paste the script body from Section 7.
7. Code: JavaScript for Unified Runtime
Use the following baseline. It demonstrates edge detection, latching, and a call to the unified pop-up API.
// TagChange_ShowAlarmPopup
// Trigger: HMI_AlarmRequest_Bit00 (Bool)
// Behavior: When the bit transitions 0->1, open pop-up screen "AlarmPopup".
// The bit must be reset by the PLC after the operator acknowledges.
import { Screen, Tags } from "HMIRuntime";
export async function TagChange_ShowAlarmPopup(ctx) {
// Read the current value of the trigger tag via the context object
const triggerValue = ctx.Value; // Boolean provided by the trigger binding
if (triggerValue === true) {
// Open the pop-up at a fixed position; the runtime will center it
// if you pass width/height and omit x/y.
Screen.OpenPopup({
screenName: "AlarmPopup",
width: 600,
height: 300,
modal: true
});
} else {
// Optional: close the pop-up on falling edge
Screen.ClosePopup("AlarmPopup");
}
}
For projects that need latching (the pop-up stays even if the PLC tag returns to 0 because the PLC pulse was only one scan long), use a memory tag on the HMI as the actual display flag:
// Latched version
import { Screen, Tags } from "HMIRuntime";
export async function TagChange_ShowAlarmPopup_Latched(ctx) {
const triggerValue = ctx.Value;
const latchTag = Tags("HMI_AlarmLatched_Bit00");
if (triggerValue === true && (await latchTag.Read()) !== true) {
await latchTag.Write(true);
Screen.OpenPopup({
screenName: "AlarmPopup",
width: 600,
height: 300,
modal: true
});
}
}
Pair the script with an Acknowledge button in the pop-up that writes false back to HMI_AlarmLatched_Bit00 and calls Screen.ClosePopup("AlarmPopup").
8. Code: VBScript Variant for Legacy Comfort Panels (V16)
For pre-V17 Comfort Panels that only support VBScript on the Loaded/Cleared events, the equivalent pattern uses a tag-trigggered property dynamization rather than a script. There is no OnChange event in WinCC Comfort VBScript; instead, use the property dynamization dialog and bind a value-evaluation expression:
' Comfort Panel V16 - property dynamization on Visibility of a hidden rectangle
' Trigger tag: HMI_AlarmRequest_Bit00
' Script: not applicable; use the dialog: Dynamizations > Appearance > Visibility
' Expression: HMI_AlarmRequest_Bit00 = 1
Then attach the pop-up open to the rectangle's Click event (force-triggered by a second invisible button, or — more reliably — migrate to WinCC Unified). The Unified path is strongly preferred for new projects.
9. Verification & Commissioning
Use the following checklist before going live on the panel:
- Compile: Project → Compile → Software (rebuild all). Resolve every warning, especially Unresolved tag reference on the script's trigger binding.
- Simulate: Use the TIA Portal Start Runtime simulation (Unified PC). Force the trigger tag in PLCSIM and confirm the pop-up appears within one acquisition cycle.
- Edge test: Toggle the bit on/off in PLCSIM and verify the script runs on both edges (or only the rising edge, depending on intent).
- Navigate test: Navigate to several other screens while the tag is low, then force the tag high. The pop-up must still appear. If it does not, the host element is in a screen window that was unloaded — move it to the start screen.
-
Modal test: With
modal: true, confirm the operator cannot reach the underlying process screen until the pop-up is acknowledged. -
Resource test: On a Comfort Panel target, check the WebClient console for the script's
console.logoutput and watch for V8 heap growth across an 8-hour shift.
10. Common Pitfalls
| Symptom | Likely cause | Fix |
|---|---|---|
| Pop-up never appears | Script attached to a Loaded event, not a dynamization | Move the script to Dynamizations → Script and bind the trigger tag |
| Pop-up appears once, then never again | Host element inside a pop-up or per-page screen window | Place the host in the start screen or main screen window |
| Pop-up appears twice on a single edge | Two host elements both bound to the same trigger | Audit the project for duplicate bindings; keep one source of truth |
| Script does not run during simulation | Tag acquisition cycle set to 0 (only on change) and tag is at its current value | Force a value change in PLCSIM, or set a 100 ms cyclic acquisition |
| Runtime error "Screen not found" | Pop-up screen name typo or screen type is not Pop-up compatible | Verify the screen name in the project tree exactly matches the string passed to OpenPopup |
| Pop-up appears but operator cannot close it | Modal flag with no close button wired | Add an Acknowledge button calling Screen.ClosePopup |
11. Advanced Patterns
Edge detection with hysteresis. When the PLC cycles the alarm bit rapidly, wrap the trigger in a debounce timer using setTimeout in the script. Cancel any pending timer at the top of the function and schedule the pop-up 250 ms out, discarding intermediate transitions.
Multi-tag triggers. Bind the script's Trigger tag field to a single composite tag (e.g., an Int containing a bitmask) and switch on the value inside the script to choose which pop-up to open. This keeps the host element count to one and avoids ordering bugs between parallel scripts.
Cross-screen reuse. Factor the pop-up logic into an exported function in a global script file under Project library → Scripts, then import it from the dynamization script. This prevents copy-paste drift between screens and makes bulk edits safe.
Auditing. Add a Tags("HMI_AuditLog").Write(...) call in the script with a timestamp retrieved via Tags("SystemTime").Read(). Operators and process engineers can later trace which alarm fires when, satisfying 21 CFR Part 11 and similar audit requirements on pharmaceutical lines.
12. Reference: WinCC Unified Script API Surface
| API call | Purpose | Notes |
|---|---|---|
Screen.OpenPopup({screenName, width, height, modal, x, y}) |
Open a screen as a pop-up | x/y optional; modal blocks underlying interaction |
Screen.ClosePopup(screenName) |
Close a specific pop-up | Pass exact screen name |
Tags(name).Read() |
Asynchronous tag read | Returns Promise; await in async function |
Tags(name).Write(value) |
Asynchronous tag write | Reflects back to PLC on the configured cycle |
ctx.Value |
Current trigger value | Provided in the script context object |
ctx.Quality |
OPC quality code of the trigger | 0 = Good, >0 = Uncertain/Bad |
13. Performance and Safety Notes
On a Unified Comfort Panel (e.g., 7" MTP700), the V8 script engine runs in a single thread shared with screen rendering. Keep dynamization scripts under 50 lines, avoid heavy loops, and never call blocking APIs such as FileSystem.Read from inside a tag-change handler. Move expensive work to scheduled scripts (Project library → Scheduled tasks) running on a 1 s cycle.
For safety-relevant alarms, do not rely solely on a pop-up driven by a script. Configure the same tag in the HMI alarm system with a class of Errors (red, with acknowledgment required) and require the operator to acknowledge in the alarm line. The pop-up is a UX enhancement; the alarm is the auditable record.
Why does my pop-up script only run when the screen is first opened?
The script is bound to the Loaded event of the screen, which only fires when the screen object is instantiated. Move the script to Dynamizations → Script on a persistent element and bind it to your trigger tag so it re-fires on every value change.
Where should I place the invisible object that hosts the dynamization script?
Place it in the start screen or the main screen window that is permanently part of the active screen tree. The object must be in a screen that is currently rendered, otherwise the script will not execute when the trigger tag changes.
Can I use this pattern on a WinCC Comfort Panel with V16 firmware?
Comfort Panels with V16 firmware do not support JavaScript dynamization. You must migrate to WinCC Unified (V17 or later), or use the property dynamization dialog with a boolean expression driving the Visibility of a hidden element.
How do I avoid the pop-up opening twice on a single alarm edge?
Use a latched HMI tag as the display flag and write to it from inside the script. The script only opens the pop-up when the trigger transitions 0→1 and the latch is currently false, then sets the latch true. The Acknowledge button in the pop-up clears the latch and closes the pop-up.
What is the recommended acquisition cycle for the trigger tag?
For most discrete alarms, 100 ms is sufficient. For sub-second response, drop to 50 ms and ensure the S7 connection has a matching update rate. Do not go below 20 ms on a Comfort Panel; the panel's internal tag database and V8 loop cannot sustain it and you risk dropped events.