Overview
WinCC Professional exposes a TagPrefix property on screen windows so that a single embedded screen can be re-pointed at a different set of PLC tags at runtime. The corresponding TagPrefix property for Panels, Comfort Panels, RT Advanced and RT Professional is documented as: "Specifies the tag prefix that is prefixed for all tags contained in the screen window. In this way, a screen that is embedded in a screen window retains access…"
WinCC Unified does not expose that convenience property on a screen window. To achieve the same result - having one button open a trend control and point it at a tag whose identity depends on a runtime value (for example, a selected breaker ID) - the developer must bind the trend's Y-axis DataSource directly with a fully-qualified string. This article documents the working JavaScript pattern, the required smartHMI:: device prefix, the index-based item access, and the runtime verification steps that confirm the binding.
Prerequisites
- TIA Portal V18 or later with WinCC Unified runtime installed on the target device (Unified PC, Unified Comfort Panel, or MTP).
- A configured HMI device whose runtime name is known. In the example below the device is named
smartHMI; the name is whatever you entered in the HMI device properties under "Device name". - A WinCC Unified screen containing a Trend control with at least one configured trend area (
TrendArea_1) and one trend (Trend_1). For multi-trend popups, configure additional trends (Trend_2,Trend_3, …) before compiling. - The HMI tags you intend to point at must be in the same namespace that will be referenced by the string. Logging tags must already exist on the HMI device; runtime substitution cannot create new tags.
- Runtime must be running and the screen must be loaded before the script is triggered - all object lookups (
Screen.FindItem) returnnullon a screen that has not been opened yet.
Why the Direct Tag-Object Approach Fails
The intuitive approach - read a tag object with HMIRuntime.Tags(...).Read() and assign it to DataSourceY.Source - does not bind the trend to the live tag:
// Does NOT establish a live binding - DataSourceY.Source expects a string, not a value object.
export function Button_1_OnTapped(item, x, y, modifiers, trigger) {
Screen.FindItem("Trend control_1").Visible = true;
Screen.FindItem("Trend control_1").TrendAreas.Item("TrendArea_1").Trends("Trend_1")
.DataSourceY.Source = HMIRuntime.Tags("Analog__{1}.PV_HMI").Read();
}
The property type of DataSourceY.Source is String. Assigning the result of .Read() coerces the value object to a string (typically "[object Object]" or a snapshot numeric), so the trend is bound to a literal, not a tag reference. The runtime never re-evaluates the string against the tag database once the assignment is made.
Working Pattern: Assign a Fully-Qualified Tag Name
The runtime re-evaluates the string on every refresh of the trend buffer. Pass the tag name as a literal string in the form <HMI device name>::<tag path>:
export function Button_1_OnTapped(item, x, y, modifiers, trigger) {
// 1. Make the trend control visible (toggle, animate, or screen window).
Screen.FindItem("Trend control_1").Visible = true;
// 2. Bind the Y source. Use INDEX, not name, for TrendAreas/Trends in the runtime API.
Screen.FindItem("Trend control_1").TrendAreas.Item(0).Trends.Item(0)
.DataSourceY.Source = "Analog__{1}.PV_HMI";
}
| Property | Design-time value | Runtime argument | Notes |
|---|---|---|---|
| Trend control object | Name (e.g. Trend control_1) |
Name string | Whitespace and underscores are preserved by FindItem. |
| TrendAreas collection | Name (e.g. TrendArea_1) |
Index (0-based) | The runtime API ignores the name argument here - always pass Item(0), Item(1), … |
| Trends collection | Name (e.g. Trend_1) |
Index (0-based) | Same restriction; .Trends("Trend_1") throws Item not found. |
| DataSourceY.Source | HMI tag path |
<DeviceName>::<Path> string |
The device prefix is required; without it the runtime searches the project namespace and fails. |
Substituting a Runtime Index (Tag Prefix Equivalent)
To make the same trend control point at different tags based on a runtime variable - the use-case the old TagPrefix property solved - read a number tag that stores the index and concatenate it into the source string:
let globalBreakerID = Tags("globalBreakerID"); // HMI tag, type Int, current selection
let ctrl = Screen.FindItem("loadStudy1");
ctrl.Visible = true;
ctrl.TrendAreas.Item(0).Trends.Item(0).DataSourceY.Source =
"smartHMI::systemInfo_meteringWL[" + globalBreakerID.Read() + "].AB_VOLTS:abVolts_1";
ctrl.TrendAreas.Item(0).Trends.Item(0).DisplayName = "AB Volts";
ctrl.TrendAreas.Item(0).Trends.Item(1).DataSourceY.Source =
"smartHMI::systemInfo_meteringWL[" + globalBreakerID.Read() + "].BC_VOLTS:bcVolts_1";
ctrl.TrendAreas.Item(0).Trends.Item(1).DisplayName = "BC Volts";
The string "systemInfo_meteringWL[0].AB_VOLTS:abVolts_1" is the fully-qualified name of an HMI logging tag. The bracketed [0], [1], …, [N-1] is the array index of a structured tag; the runtime resolves it on every buffer update, which makes this the functional equivalent of the WinCC Professional TagPrefix for trend sources.
Binding a User-Selected Tag Stored in a String Tag
If the tag name itself is held in a string tag, read it and concatenate the device prefix in front:
// HMI tag 'selectedSource' is a String tag whose value is the path of the tag to plot.
let path = Tags("selectedSource").Read();
let ctrl = Screen.FindItem("Trend control_1");
ctrl.TrendAreas.Item(0).Trends.Item(0).DataSourceY.Source = "smartHMI::" + path;
selectedSource can force the trend to bind to any tag the HMI has read rights on, which is an information disclosure vector. Use a whitelist mapping (numeric ID → string) when the source is exposed to operators.Trend Popup Pattern (Show-on-Tap)
Place the trend control off-screen, inside a container that is hidden by default, and toggle visibility from a button event. Combine with DisplayName for a clear legend:
export function Button_1_OnTapped(item, x, y, modifiers, trigger) {
let ctrl = Screen.FindItem("Trend control_1");
// Toggle visibility
ctrl.Visible = !ctrl.Visible;
if (!ctrl.Visible) return;
// Re-bind on every show so that the displayed tag matches the current selection
let id = Tags("globalBreakerID").Read();
ctrl.TrendAreas.Item(0).Trends.Item(0).DataSourceY.Source =
"smartHMI::systemInfo_meteringWL[" + id + "].AB_VOLTS:abVolts_1";
ctrl.TrendAreas.Item(0).Trends.Item(0).DisplayName = "AB Volts - Breaker " + id;
// Optional: clear cached values to force an immediate fetch
ctrl.TrendAreas.Item(0).Trends.Item(0).DataSourceY.Deactivate();
ctrl.TrendAreas.Item(0).Trends.Item(0).DataSourceY.Activate();
}
The Deactivate() / Activate() pair is useful when the user changes selection while the trend is already visible and the trend buffer still holds the previous series. Without the re-activation, the new tag will not be requested until the next acquisition cycle - typically 1-2 s, which is long enough to look like a fault.
Faceplate Limitations
WinCC Unified faceplates do not support the Trend control as a contained element (as of V20). If the design requires one faceplate to host a trend, the working alternatives are:
- Place the trend in a separate "detail" screen and have the faceplate instance toggle that screen's visibility via a screen window.
- Use the Process tag property interface on the faceplate and pass the
<DeviceName>::<Path>string in from the parent screen; bind the trend on the parent screen, not inside the faceplate. - Use the Trends control in a popup window opened from the faceplate's "Change" or "Detail" button - the same JavaScript pattern applies because the popup inherits the device namespace.
Configuration Behind the Scenes: Where the Prefix Comes From
The <DeviceName>:: prefix is the runtime name of the HMI device. It is set in the device properties and is the same identifier used by the "Settings for tags (RT Unified)" editor when synchronizing PLC tags into the HMI namespace. If you rename the HMI device after writing the JavaScript, every string assignment must be updated. To avoid that maintenance hazard, store the device name in a project constant and concatenate it at the call site:
const DEVICE = "smartHMI"; // change in one place if the device is renamed
let id = Tags("globalBreakerID").Read();
Screen.FindItem("loadStudy1").TrendAreas.Item(0).Trends.Item(0).DataSourceY.Source =
DEVICE + "::systemInfo_meteringWL[" + id + "].AB_VOLTS:abVolts_1";
Runtime Verification
- Compile the HMI project to the target device. A syntax error in the script (e.g.
Trends("Trend_1")instead ofTrends.Item(0)) will be reported under Compile > Scripts in the TIA Portal output. - Open the screen on the runtime. Trigger the button event. In a Trend control with online diagnostics enabled, the Status field shows the resolved tag name; it must start with the HMI device prefix.
- Change the value of the index tag (e.g.
globalBreakerID) on the HMI. The trend must re-buffer with the new series within one acquisition cycle (default 1 s for WinCC Unified). - In the runtime's diagnostic view (RT Unified > Diagnostics > Tags), confirm that the bound tag's value updates at the configured logging rate. If Quality shows Bad, the device prefix is wrong.
- Click the button a second time. The trend must remain bound (the
Visible = !Visibletoggle does not clear theSourcestring).
Troubleshooting Matrix
| Symptom | Likely cause | Remedy |
|---|---|---|
| Trend shows "No data" and Status = Configuration error |
DataSourceY.Source is a value object, not a string (the .Read() pattern). |
Pass the tag name as a quoted string. Do not read the tag. |
Runtime exception Item not found on Trends("Trend_1")
|
The runtime API uses index arguments, not names. | Use Trends.Item(0), Trends.Item(1), …. |
| Trend is blank, Quality = Bad | Missing or wrong smartHMI:: device prefix. |
Prepend <HMI device name>::. Verify the device name in HMI properties. |
| Trend shows the old series after a new index is written | Buffer not refreshed on rebind. | Call DataSourceY.Deactivate() then Activate() after assigning Source. |
| Trend works in simulation but not on the panel | Device prefix differs between the simulation target and the real device. | Use a project constant for the device name; check the panel's Device name property. |
| Tag updates are delayed by several seconds | Logging tag acquisition rate is too low. | Reduce the acquisition cycle in the logging tag's properties (typical minimum: 500 ms; 100 ms for fast signals). |
Script compiles but Screen.FindItem returns null
|
Trend control is on a screen that is not yet loaded, or it is inside a faceplate (not supported). | Move the trend to a detail screen or a popup, and ensure that screen is loaded before the script runs. |
| Multiple identical curves overlaid | Two Trends.Item(N) bindings point to the same source string. |
Verify the source string for each trend index; consider building an array of (source, displayName) tuples and looping. |
Field-Proven Checklist
- Use
Item(0)on bothTrendAreasandTrends; do not pass the design-time name. - Always include the
<DeviceName>::prefix on the source string. The TIA Portal design-time value is unqualified, but the runtime value must be qualified. - Re-activate the data source on every re-bind to avoid a one-cycle delay when the user changes the index while the trend is visible.
- Wrap index concatenation in a string-building helper so that the same code can drive
DisplayName, the Y-source, and any tooltip or archive reference. - Validate index bounds (
0 <= id < N) before concatenating, otherwise a single out-of-range index can blank the trend for the rest of the session. - Put the trend in a separate popup screen; do not rely on faceplate containment for trend controls in V18-V20.
FAQ
Does WinCC Unified support a TagPrefix property on screen windows like WinCC Professional?
No. WinCC Unified does not expose a TagPrefix property on screen windows; the WinCC Professional/Comfort TagPrefix property is documented only for Panels, Comfort Panels, RT Advanced and RT Professional. The equivalent behaviour in Unified is to write the fully-qualified tag name (with the device prefix) into the trend's DataSourceY.Source string at runtime.
Why does assigning HMIRuntime.Tags(...).Read() to DataSourceY.Source fail?
DataSourceY.Source is typed as String. Read() returns a value object (or a snapshot of the current value), not a tag reference. The runtime coerces it to a string and binds to that literal, so the trend never refreshes from the live tag. Pass a quoted string of the form "<DeviceName>::<TagPath>" instead.
What is the smartHMI:: prefix in the source string?
It is the runtime device name of the HMI, set in the HMI device properties. The runtime requires the device prefix to resolve the tag inside the HMI's namespace, the same convention used when synchronising PLC tags into the RT Unified tag database. Replace "smartHMI" with whatever you entered in the device's "Device name" field.
Can I bind multiple trends in the same trend control from JavaScript?
Yes. Iterate over Trends.Item(0)..Trends.Item(N-1) and assign each DataSourceY.Source to a different fully-qualified tag string. Always use the index, not the trend's design-time name, in the runtime API.
Why does the trend keep showing the previous series after I change the index tag?
The trend buffer caches the previously bound series until the next acquisition cycle. Call DataSourceY.Deactivate() followed by DataSourceY.Activate() immediately after assigning the new Source string to force an immediate fetch of the new series.