Closing a Popup Faceplate from an Internal Button in TIA V16

David Krause11 min read
HMI ProgrammingSiemensTutorial / How-to
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

1. Problem Overview

Engineers building WinCC Unified screens in TIA Portal V16 frequently need a popup faceplate (named PopUp) that can be dismissed by a button located inside that popup. The popup is launched from another faceplate (named PopupButton) that itself sits on a screen. This pattern is standard for confirmation dialogs, warning banners, and parameter entry dialogs.

The expected flow is:

  1. Operator clicks PopupButton on the main screen.
  2. WinCC Unified opens PopUp as a popup window.
  3. Operator interacts with controls inside PopUp.
  4. Operator clicks a button inside PopUp; the popup closes.

Step 4 fails in V16 because the V17+ scripting helper Faceplate.Close() is unavailable. The V16 runtime exposes only CloseFaceplateInPopup, which must be called on the popup window container, not on the faceplate instance itself. This is the most common failure point and the topic of the rest of this guide.

2. Prerequisites

  • TIA Portal V16 Update 4 or later (WinCC Unified V16 scripting runtime).
  • Configured WinCC Unified Runtime (RT Unified) on a Unified PC, Unified Comfort Panel, or IPC.
  • An HMI device with two faceplate types created: PopupButton and PopUp.
  • A screen containing a popup window object (e.g., PopupWindow).
  • Working knowledge of the V16 JavaScript-based scripting environment.
Note: All code examples below are V16-compatible. The newer Faceplate.Close() API was introduced in TIA V17 and is documented in the Siemens TIA Portal V20 Unified manual (local script example). On V16 you must use the older CloseFaceplateInPopup approach shown here.

3. Root Cause Analysis

Three architectural constraints in V16 explain why the naive close script does nothing:

  1. No Faceplate.Close() scripting helper. That convenience method ships with TIA V17+. In V16, no script-level method closes the active popup from inside the faceplate instance. The script must reach up the object hierarchy to the popup window container and call CloseFaceplateInPopup explicitly.
  2. Faceplate scope isolation. A popup faceplate instance is a separate runtime object from the parent faceplate that opened it. Tag interfaces defined on PopupButton (such as ButtonFunction) are not visible inside PopUp.
  3. Script execution context. A button's Click script attached inside a faceplate type runs in the context of that faceplate instance. The script's this and item.Parent refer to the faceplate container, not the popup window. A direct .Close() call has no target.

To diagnose the issue, add a temporary trace line and inspect the object model in the runtime trace viewer:

export function CloseButton_OnClick(item) {
    HMIRuntime.Trace("item name: " + item.Name);
    HMIRuntime.Trace("item.Parent name: " + item.Parent.Name);
    HMIRuntime.Trace("item.Parent.Parent name: " + item.Parent.Parent.Name);
}

You will observe that item.Parent is the PopUp faceplate container and item.Parent.Parent is the popup window. The latter is what owns the CloseFaceplateInPopup method.

4. Faceplate Object Hierarchy

Main Screen item.Parent (on root screen) PopupButton Faceplate Interface: ButtonFunction Click → OpenFaceplateInPopup() Instance scope: Screen level PopupWindow (container) Object name: "PopupWindow" Holds PopUp faceplate instance Owns CloseFaceplateInPopup() PopUp Faceplate Contains CloseButton control item.Parent.Parent = PopupWindow Script target for close call instantiates hosts

5. Solution 1: Local Script in the PopUp Faceplate (V16 Recommended)

The supported V16 pattern is to attach a JavaScript to the internal button's Click event and navigate up the object tree to the popup window container, then call CloseFaceplateInPopup with the window's object name.

5.1 Step-by-Step Implementation

  1. Open the PopUp faceplate type in the TIA V16 editor.
  2. Insert a Button control, name it CloseButton.
  3. Open Properties → Events → Click.
  4. Add a new script and assign it to the Click event.
  5. Enter the V16-compatible code:
export function CloseButton_OnClick(item) {
    // Walk up the object tree: button -> faceplate container -> popup window
    let popupWindow = item.Parent.Parent;
    // Close the faceplate instance inside the popup window by window name
    let result = popupWindow.CloseFaceplateInPopup("PopupWindow");
    HMIRuntime.Trace("CloseFaceplateInPopup result: " + result);
}
  1. Ensure the popup is opened from the parent faceplate's button script:
export function PopupButton_OnClick(item) {
    let screen = item.Parent;
    // OpenFaceplateInPopup(windowName, faceplateType, parameters, modal, posX, posY)
    screen.OpenFaceplateInPopup("PopupWindow", "PopUp", "", false, 0, 0);
}

5.2 Function Parameter Reference

Parameter Type Value in example Description
windowName String "PopupWindow" Object name of the popup window on the screen. Case-sensitive.
faceplateType String "PopUp" Faceplate type name as defined in the HMI library.
parameters String "" Optional parameter string passed to the popup's Opened event.
modal Boolean false If true, blocks input to the underlying screen.
posX, posY Integer 0, 0 Top-left coordinate of the popup window in pixels.

The full V16 method signature is:

Boolean CloseFaceplateInPopup(String windowName)
Boolean OpenFaceplateInPopup(String windowName, String faceplateType,
                             String parameters, Boolean modal,
                             Int32 posX, Int32 posY)

For the V20 equivalent with refinements to type handling and helper objects, see the official Siemens TIA V20 manual: Configure faceplate as pop-up.

5.3 Defensive Coding Pattern

Hard-coding the string "PopupWindow" is fragile. Query the name at runtime and guard against nulls:

export function CloseButton_OnClick(item) {
    let popupWindow = item.Parent.Parent;
    if (popupWindow === null || popupWindow === undefined) {
        HMIRuntime.Trace("ERROR: popupWindow reference is null");
        return;
    }
    let windowName = popupWindow.Name;
    let ok = popupWindow.CloseFaceplateInPopup(windowName);
    if (!ok) {
        HMIRuntime.Trace("Close failed for window: " + windowName);
    }
}

6. Solution 2: Close the Popup from Outside (Screen or Parent Faceplate)

Sometimes the close trigger lives outside the popup — for example, a system key, an external alarm, or a button on the main screen. The same CloseFaceplateInPopup function applies, but called from a different scope:

// Attached to a Cancel button on the main screen
export function CancelButton_OnClick(item) {
    item.Parent.CloseFaceplateInPopup("PopupWindow");
}

From the parent PopupButton faceplate, you would navigate up one level before calling:

export function PopupButton_OtherClick(item) {
    let screen = item.Parent; // parent faceplate's parent is the screen
    screen.CloseFaceplateInPopup("PopupWindow");
}
Field note: Calling close from a script inside a modal popup can deadlock the runtime in V16. Set modal=false when opening if you intend to close from outside, or schedule the close on a 100 ms delay using HMIRuntime.SetTimeout(...).

7. Passing a Tag Interface from PopupButton to PopUp

The second question from the source is whether a tag defined in the PopupButton faceplate interface (e.g., ButtonFunction) can be used directly inside the PopUp faceplate. The short answer is no, not directly. Faceplate interfaces are scoped to the instance, and a popup faceplate is a separate instance.

7.1 Why Direct Access Fails

A faceplate type is a self-contained template. When instantiated, the runtime creates a fresh object with its own copy of the interface tags. The PopUp instance has no compile-time or runtime reference to the PopupButton instance that opened it.

7.2 Option A — Pass a Parameter String at Open Time

The third parameter of OpenFaceplateInPopup carries a string into the popup's Opened event. This is the cleanest V16 mechanism.

// In PopupButton faceplate, Click event
export function PopupButton_OnClick(item) {
    let screen = item.Parent;
    let functionCode = item.ButtonFunction; // read this faceplate's interface tag
    let paramString = "mode=" + functionCode + ";source=PopupButton";
    screen.OpenFaceplateInPopup(
        "PopupWindow", "PopUp", paramString, false, 0, 0
    );
}

Inside the PopUp faceplate, parse the string in the Opened event:

// In PopUp faceplate, Opened event
export function PopUp_OnOpened(item, parameters) {
    HMIRuntime.Trace("Popup opened with: " + parameters);
    // Simple parser for "key=value;key=value" format
    let parts = parameters.split(";");
    for (let i = 0; i < parts.length; i++) {
        let kv = parts[i].split("=");
        if (kv[0] === "mode") {
            let mode = parseInt(kv[1]);
            // store in a local faceplate tag for use in subsequent scripts
            item.Parent.LocalMode = mode;
        }
    }
}

7.3 Option B — Use a Global HMI Tag

For complex contexts (multiple values, frequent updates), use a global HMI tag that both faceplates reference. This decouples the popup from the caller.

  1. Create a global HMI tag PopupContext (type: Int or WString) in the HMI tag table.
  2. Write the value before opening:
export function PopupButton_OnClick(item) {
    HMIRuntime.Tags.SysFct.Set("PopupContext", item.ButtonFunction);
    item.Parent.OpenFaceplateInPopup(
        "PopupWindow", "PopUp", "", false, 0, 0
    );
}
  1. Read it inside the popup:
export function CloseButton_OnClick(item) {
    let context;
    HMIRuntime.Tags.SysFct.Get("PopupContext", function(value) {
        context = value;
        HMIRuntime.Trace("Closing with context: " + context);
    });
    item.Parent.Parent.CloseFaceplateInPopup("PopupWindow");
}

7.4 Option C — Mirror the Tag in Both Faceplate Interfaces

If the popup is always paired with a parent faceplate, define a tag with the same name in both faceplate interfaces. Configure the popup instance's interface tag to point to the same underlying HMI tag or PLC address. This keeps the popup self-contained but couples the two faceplate types at design time.

7.5 Option Comparison

Option Coupling Type safety V16 compatible Best for
Parameter string Low None (string only) Yes Single value, simple cases
Global HMI tag Medium Yes (typed) Yes Multiple values, reusable popup
Mirrored interface High Yes (typed) Yes Always-paired faceplate pairs

8. Verification

After implementing the close script, perform the following checks before commissioning.

8.1 Compile-Time Checks

  1. Compile the HMI project (HMI device → Compile → Software (all)). Zero errors and zero warnings on faceplate scripts.
  2. Confirm the popup window object is referenced consistently: its name in the screen's Pop-ups folder matches the string passed to OpenFaceplateInPopup and CloseFaceplateInPopup.
  3. Validate the faceplate interface tag names: case-sensitive in V16, including trailing spaces.

8.2 Runtime Checks

  1. Download the project to the RT Unified target.
  2. Start the runtime and open the screen containing the PopupButton instance.
  3. Click PopupButton — verify the PopUp faceplate appears.
  4. Click the internal CloseButton — verify the popup closes.
  5. Open the HMI Runtime Trace Viewer and confirm CloseFaceplateInPopup result: true.
  6. Test the open/close cycle 10+ times; V16 has known race conditions if the close fires within 50 ms of open.

8.3 Verification Matrix

Test Expected Result Pass/Fail Criteria
Click PopupButton PopUp faceplate appears Visual confirmation + trace Open=true
Click CloseButton PopUp faceplate disappears Visual confirmation + trace Close=true
Tag interface value passed PopUp reads correct ButtonFunction value Trace Popup opened with: mode=…
Modal=true behavior Background screen input blocked Click outside popup — no event fires
Close from external Cancel PopUp closes from screen-level script Visual confirmation + trace
10x rapid cycle No deadlocks, no ghost popups All 10 cycles complete cleanly

9. Common V16 Errors and Resolutions

Error / Symptom Root Cause Resolution
Click does nothing; no trace output Script not attached to Click event, or event misconfigured Re-attach script in Properties → Events → Click
Function CloseFaceplateInPopup not found Wrong object: called on faceplate instead of popup window Use item.Parent.Parent.CloseFaceplateInPopup(...)
Object reference not set to an instance Button is on the root screen, not inside the popup Verify the button is placed inside the PopUp faceplate type
Window 'PopupWindow' not found String mismatch between open and close calls Use a project-wide constant for the window name
Popup closes but reopens immediately Open script is also bound to a different event firing on close Move open call to Click only; check for Value Change triggers
Modal popup cannot be closed from outside Modal input block prevents event delivery Set modal=false or use HMIRuntime.SetTimeout(..., 100) to defer close
Parameter string arrives empty in popup Open call passes "" literally Pass non-empty string; check concatenation in script

10. V16 vs V17+ Capability Comparison

Capability TIA V16 TIA V17+ TIA V20
Faceplate.Close() helper Not available Available Available, refined
CloseFaceplateInPopup(windowName) Available Available Available
OpenFaceplateInPopup(...) Available Available Available with extended overloads
Tag interface inheritance None None None
Modal popup API maturity Limited Full Full
Helper object accessors on item Manual Parent navigation Helper properties Helper properties
Documentation coverage Sparse Comprehensive Comprehensive

11. Migration Path to V17 or Later

When the project is upgraded to TIA V17 (or V18/V19/V20), the close logic simplifies to a one-liner. The script becomes portable with minor edits:

// V17+ equivalent
export function CloseButton_OnClick(item) {
    Faceplate.Close();
}

The V20 manual documents the local script pattern in detail, including type-safe parameter passing. Refer to the V20 example: create local script to close the pop-up and the V20 example: configure faceplate as pop-up for the modern equivalents of the V16 patterns shown here.

12. Best Practices

  • Centralize the popup window name. Define const POPUP_WIN = "PopupWindow" in a shared script module; reference it from every open and close call.
  • Trace aggressively during V16 development. V16 has minimal IntelliSense and the runtime trace is the fastest way to confirm object hierarchy.
  • Prefer the local script pattern over screen-level scripts for close actions; the close logic travels with the faceplate type and survives screen refactors.
  • Document parameter string formats. Since V16 has no structured parameter object, encode values as key=value;key=value and document the schema in the faceplate header comment.
  • Keep faceplate interfaces minimal. Expose only what the popup actually needs. Avoid passing the entire parent context.
  • Test rapid open/close cycles. V16 has known race conditions when close is called within 50 ms of open; insert a small delay if ghosts appear.
  • Avoid Faceplate.Close() on V16. The method does not exist; the runtime will silently fail or throw a script error. Use CloseFaceplateInPopup until the project is upgraded.

FAQ

Why does nothing happen when I press the close button inside my popup faceplate in TIA V16?

The script is running in the faceplate instance, not the popup window. In V16, navigate to the popup window with item.Parent.Parent and call popupWindow.CloseFaceplateInPopup("PopupWindow"). The V17+ Faceplate.Close() method is not available in V16.

Can a popup faceplate read a tag defined in the parent faceplate's interface?

No. Faceplate interfaces are scoped to their instance. Pass the value through the third parameter of OpenFaceplateInPopup(...) as a string, or use a global HMI tag that both faceplates reference.

Does Faceplate.Close() work in TIA Portal V16?

No. That scripting helper was introduced in TIA V17. On V16 you must call CloseFaceplateInPopup on the popup window container object.

How do I find the popup window's object name?

Open the screen in the TIA editor, expand the Pop-ups folder in the screen tree, and read the object name. You can also query it at runtime with item.Parent.Parent.Name from a script inside the popup.

Can I close a modal popup from an external button on the main screen?

Yes, but V16 has known issues where modal blocking prevents the close event from being delivered. Set modal=false when opening, or wrap the close call in HMIRuntime.SetTimeout(..., 100) to defer it past the modal input block.

Back to blog