How Does Perspective Tree Enforce Single Selection?

Stefan Weidner5 min read
HMI ProgrammingOther ManufacturerTutorial / 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

Ctrl-clicking more than one node leaves multiple tags selected in an Ignition Perspective 8.1 Tree. The Perspective Tree has no Single/Multiple selection property, so the practical control point is the component’s onItemClicked event. The event action must reduce both props.selection and props.selectionData to the last clicked item.

Where does multiple selection enter the data path?

Follow the packet from the operator’s input to the rendered state. A mouse click, touch action, or modified keyboard click reaches the browser component first. The Tree applies its built-in selection behavior, then the click event exposes the selected node through event.itemPath. The action script rewrites the selection properties, and the updated properties drive the next rendered state.

Path stage Data or setting Check
Physical input Click or Ctrl-click Confirm the component receives the intended node click.
Tree selection handler Built-in multiple-selection behavior Watch props.selection while selecting two nodes.
Component event onItemClicked and event.itemPath Confirm the event fires for every clicked node.
Normalization script props.selection and props.selectionData Confirm both arrays contain no more than one entry.
Rendered result Tree highlight and downstream bindings Confirm only the last clicked node remains active.

This behavior belongs to the component state path, not the tag communication path. A network address, protocol port, or tag-provider setting cannot change how the Tree interprets Ctrl-click. Start at the operator input and component properties before investigating communications.

Which Tree properties must remain synchronized?

The Tree represents selection in two related properties. props.selection contains selected item paths. props.selectionData contains the corresponding selection records used by bindings, scripts, or other components. Trimming only one array creates an inconsistent state: the visible highlight may show one node while downstream logic still sees multiple records.

Property Required single-selection state Recurring failure
props.selection One path for the retained node, or an empty array when deselection is allowed Multiple highlights remain when earlier paths are not removed.
props.selectionData One record matching the retained path, or an empty array Bindings process stale selections when only the path array is changed.
event.itemPath The path of the node that generated the click Writing the raw index list instead of the Tree’s slash-delimited path produces the wrong selection format.

The last clicked record is at the end of props.selectionData. Retaining selectionData[-1] therefore keeps the record aligned with the clicked item. Before adding the action, select two nodes and verify that both selection properties expand. That proves the fault is inside selection-state handling and identifies the two properties the action must normalize.

How do I configure the single-selection action?

Add a script action to the Tree component’s onItemClicked event. Build the slash-delimited item path from event.itemPath, replace the path array with that one value, and retain only the final selection-data record.

def runAction(self, event):
    itemPath = '/'.join([str(_) for _ in event.itemPath])
    self.props.selection = [itemPath]
    if len(self.props.selectionData) > 0:
        self.props.selectionData = [self.props.selectionData[-1]]
  1. Select the Perspective Tree component.
  2. Open its event configuration and choose onItemClicked.
  3. Add a script action and enter the code above.
  4. Save the view and open it in an active Perspective session.
  5. Click one leaf, then Ctrl-click another leaf.
  6. Inspect props.selection and props.selectionData. Each must contain exactly one entry for the last clicked leaf.

The script normalizes the result after each click; it does not add a missing component selection mode. The built-in handler can process the modified click before the event action reduces the arrays. The acceptance check is the stable post-event state: one path, one matching data record, and one active downstream selection.

How do I prevent branch nodes from becoming selected?

Single selection and branch selectability are separate decisions. If operators may select only terminal tag nodes, traverse props.items using the indices in event.itemPath. Write the selection only when the resolved node has no child items.

def runAction(self, event):
    itemPath = '/'.join([str(_) for _ in event.itemPath])
    node = self.props.items[event.itemPath[0]]
    for index in event.itemPath[1:]:
        node = node.items[index]
    if not node.get('items'):
        self.props.selection = [itemPath]
        if len(self.props.selectionData) > 0:
            self.props.selectionData = [self.props.selectionData[-1]]

The first index resolves a root item; each remaining index descends one level. The final test treats a node without child items as a leaf. This implements the effect sought when branchNodeSelectable must be disabled while retaining single selection for leaves.

Test one branch and one leaf before proceeding. Clicking the branch must not replace the current valid leaf selection. Clicking the leaf must leave one entry in each selection property.

How should deselection be handled?

The basic action always writes the clicked path back to props.selection. It therefore does not implement a clear-all gesture. Decide whether the view requires exactly one selection or at most one selection before adding more logic.

Required behavior Empty state allowed? Action
Exactly one selected node No Use the basic script; every accepted click writes one path.
Zero or one selected node Yes Detect the component’s empty post-click selection and clear both arrays together.
Leaf nodes only Depends on view requirements Combine the empty-state policy with the leaf-node traversal.

Observe props.selection and props.selectionData while clicking an already selected item. If the component produces an empty state for that gesture, preserve it by writing an empty array to both properties instead of restoring itemPath. Do not clear one property without the other. Repeat the same check with Ctrl held because modifier handling can follow a different component path.

How do I verify the complete selection path?

Run a test matrix against the published view, including every input method operators use.

  1. Click leaf A normally. Confirm one path and one matching data record.
  2. Click leaf B normally. Confirm B replaces A.
  3. Hold Ctrl and click leaf A, then leaf B. Confirm only B remains after each event completes.
  4. If range selection is available to the client, repeat with its keyboard modifier and confirm the same one-item result.
  5. Click a branch when branch selection is prohibited. Confirm the branch does not replace the retained leaf.
  6. Exercise the chosen deselection gesture. Confirm both arrays become empty together, or confirm the existing node remains selected when the view requires exactly one.
  7. Trigger every binding or navigation action that consumes props.selectionData. Confirm it processes only the record matching props.selection[0].

A visual single highlight is insufficient by itself. The passing end-to-end state is one rendered node, one path in props.selection, one corresponding record in props.selectionData, and one downstream action for the last accepted click.

FAQ

Can I set the Perspective Tree to single selection with a property?

No. The Perspective Tree in Ignition Perspective 8.1 has no Single/Multiple selection property for this behavior. Normalize the state in onItemClicked.

Does Ctrl-click bypass the single-selection script?

No. Ctrl-click may invoke the Tree’s built-in multiple-selection behavior first, but the event action then replaces the result with the path from event.itemPath.

Can I allow selection only on leaf nodes?

Yes. Traverse props.items with event.itemPath and update the selection only when the resolved node has no child items.

Does selectionData need to be trimmed with selection?

Yes. After the final Ctrl-click test, verify that props.selection contains one last-clicked path and props.selectionData contains only its matching final record.

Back to blog