Set Visibility of Template Instance in Repeater with Dynamic Expression

Is it possible to set visibility of an instance of a template within a template repeater dynamically, based on an expression that uses the value of an indirect tag bound to a template custom property?

The way that I think this would have to work is that all the custom properties of the original template are copied as custom properties within the template repeater to an indirect tag that has a dynamic instance integer. In my case, for example there is a circle that turns from red to green when an input off an aux contact on a motor starter goes high. The path to the custom property on the original template looks like:

controls_unitop.unitop::equipment_1.servo_b.cfm_vis_

I think I could add a custom property to the template repeater indirectly like so

controls_unitop.unitop::equipment_{1}.servo_b.cfm_vis

Ok, so now every instance of cfm_vis is bound dynamically to an equipment #… right? If not please steer me in the right direction, I am familiar with using the template repeater, but I have not used it where I have a template custom property that is linked to a PLC tag dynamically. This functionality works by the way, I have a custom property that is mapped from a few inputs in a UDT to a PLC path. The problem is that I have to copy the template over and over again and so I am nesting many instances of this template within another template – a template repeater seems like a much better, less labor intensive (everytime we come up with a new control template for a given piece of equipment) option.

However the way that it works now is that instances of the templates have visibility based on expression, so that as a person fills in basic info it builds this control screen automatically and a header (also a template I would like to repeat) are displayed based on whether the “equipment_type” changes:

{controls_unitop.unitop::equipment_4.equipment_type}='' &&({controls_unitop.unitop::equipment_3.equipment_type}!= {controls_unitop.unitop::equipment_5.equipment_type}) &&{controls_unitop.unitop::equipment_5.equipment_type}!=''

Ultimately this expression needs to be dynamic with the equipment number

Here is what the “monolithic” UDT looks like where I would like all configuration to take place:




So these standard PLC UDTs have a 1:1 relation with the original template customer property. However there are many different equipment types, hence the visibility requirement for a given template. For example, for the servo template to be visible, the equipment type has to = servo:

{controls_unitop.unitop::equipment_5.equipment_type}='servo'&& {controls_unitop.unitop::equipment_5.equipment_type_version}=1

Hopefully you guys/gals can see what I am after. Ultimately I want the correct type of control to be visible for the equipment type but I don’t want to have to copy and paste (and nest) a bunch of template instances within a higher level template, rather I would like to leverage indirect binding and template repeater. The complication is there are already a bunch of dynamic property/tag bindings that exist for each template type. Once it is all set up it works great as is, but every time I need to add an equipment type, I need to copy 32 instances of the template into the higher level template (32 because that is what I have room for on the widescreen version of our “Controls” template).

What I am really after is
(1) confirm that I can maintain dynamic binding to PLC tag through template custom property > template repeater custom property > dynamic OPC path in UDT (again this works minus the repeater)
(2) how to refer to a template instance custom property dynamically with indirect binding in the template repeater and/or in the expression editor
(3) how to set visibility, I imagine ultimately at the highest level with an expression that references indirect tag binding from (1) and (2).

I am happy to clarify if need be as I will mindlessly be copying and pasting templates over and over again to fill out our new widescreen format until I or someone else can come up with solution that uses the template repeater + indirect binding (it is switching to a larger monitor that has allowed me this flexibility, on 4:3 we had a self-imposed SCADA style requirement that we wouldn’t put more than 7 pieces of equipment per screen).

Consider using the repeater’s dataset mode instead of count mode. Pre-filter the dataset to exclude the instance numbers that should be hidden… then they simply won’t exist in the repeater.

Pre-filter the dataset to exclude the instance numbers that should be hidden… then they simply won’t exist in the repeater.

Whether they hide or not is based dynamically on values programmed in the UDT. I can't prefilter anything because whether it is displayed or not depends on configurable input. What I am trying to do is keep programming the HMI as simple as possible. If done correctly today a person could fill out these four fields for each valve/motor within a given unit operation:

image

The controls screen will build itself based on this user input for each piece of equipment. The way it works today however is that I have 32 instances of each equipment type template all with their own visibility expression. It works great as is, but I want to leverage the power of the repeater as opposed to copying and pasting the template and then modifying the visibility expression for each template.

I hope this makes more sense.

By pre-filter, I meant script it. You can browse the tag folder you are given, read all of the visibility tags, and dynamically construct the dataset you need.

Ah, I see what you are saying now. I think I could create a template custom visibility property that is built from dynamic strings that make up an expression. Then use that single boolean in a dataset for repeat behavior.

Assuming this is possible, I am still unclear on mapping from the template custom properties that are ultimately tied to PLC tags through a repeater. Right now the template custom properties are mapped individually to each entry in “the equipment_#” via configuration on the higher level template. I am still wrestling with whether it as simple as mapping a copy of the custom property that exists in the template at the template repeater level except instead of how I have it now where it is 1:1 as in:


I would like to use the equipment_{#} as the indirect portion and map the property indirectly but I am not quite sure I can do it. I am trying it as I type this, but if someone has experience, or best practice I am trying to get some insight from some seasoned veterans.

Don’t bother with the visibility binding. The instances that would be hidden simply won’t be there at all. The dataset just needs a column to pass the instance number for your indirect bindings. Or the string for the path ( pac_path ? ).

I am not following now, excuse my ignorance. If I just use the instance number it will just repeat 32 times, or as many rows as I put in the data set, right? I need certain rows to to not be visible based on whether the equipment type changes, in which case a different template repeater, repeating a different equipment’s control template will display (based on that templates conditional visibility expression).

I guess I am not grasping how anything would be hidden, without some sort of dynamic expression that says if equipment_type_1 != servo, then don’t display this instance of the servo control block. Likewise I have another “header” template that has conditional visibility where if equipment_type_1 != equipment_type_3, then a header will be visible. Originally when I asked this questions I was after some sort of dynamic expression like if equipment{#} != equipment{#+2} then display header.

I like the idea of using the dataset instead count, I think that is going to work I just need to wrap my head around how it is dynamically going to show or hide anything with just an instance # as a template parameter row.

It is hard to explain without context the UDTs that are configured to build the HMI control screen, versus the UDTs that have a dynamic path to a PLC tag through multiple nested templates. Sorry I wish I could be more concise with my issue!

By omitting the row of the dataset when that instance is not applicable. You could have a dataset with rows containing 1, 5, 6, 7, 9, 10 as instance numbers. Only those six rows would produce template instances in that repeater. You would script the production of the dataset upon window open or other convenient event.

Ah, yes I forgot about the scripting. Where and how does one trigger a window open even script, in a gateway script on a system tag change, in a client script on a system tag change, or is there some way to do it at the component scripting level?

One other thing, testing the idea of this out, if I have instance numbers 5,6,7,8 manually entered into my dataset its not as though it skips the 1-4 positions. It just starts displaying them at the top of the of the template repeater. I probably am missing something about how to construct the dataset to omit rows properly.

I am now utterly confused. We seem to have a different idea of "skip". This is precisely what I thought you were aiming for.

Perhaps this will frame up the issue a little more clearly. I need row 4-6 to always occupy the same space physically on the window. In this application it does not do any good to have rows 4-6 , even if they belong to the correct equipment instance, occupy the same space that 1-3 would have. Currently there are three equipment types (with many more to come) that could be in this same space (a control screen template composed of many nested templates). Right now, with separate templates and visibility conditions, I can make them appear in the correct location simply by configuring a few values in a UDT. Does this make more sense?

Ok. Then you do need to bind visibility. Either pass the path to the UDT as a string, or construct that string path from the ID you pass. Then use indirect binding within the template to obtain the appropriate visibility bits, with the visibility property(ies) private to the template. Then you can include the other IDs in your dataset and they will occupy the space.

If you are using the templates in situations where the visibility cannot be derived from an indirect off of a tagpath, you will need to leave that property public, and include a column for it in your repeater dataset.

The issue that I see trying to do it this way is that I don’t know how to get at visibility of an individual instance within the repeater. It doesn’t seem like I can target the visibility in any intuitive way, and I may have to approach it by expressions on padding between rows instead.

Add a parameter to each template. In your dataset, pass a value to this parameter - whether to show or not. On the root level of the template, bind the visible property to your custom parameter.

Ah, this may just work if I group all the subcomponents in the root template and use that visbility (which have all sorts of dynamic visibility hence the mapping all the way up to PLC boolean values). I think the tricky part will be an expression composed of indirect tag values one template level higher.

Let me summarize some template behavior to make sure we are on the same page:

  • Templates have public and private custom properties. Private properties are bindable within the template, just like properties of the various components in the template. Public properties can be used in bindings in the template, but not bound from within. Scripts within the template can assign to either kind.
  • Templates are instantiated in windows or other templates using one of three components:
  1. Simple Template Instance. This exposes the public properties of the Template as if its own custom properties. Bindable like any custom property.
  2. Template repeater. This sets the public properties of the repeated template as follows: In “count” mode, only the one public property (selected by index property name) for the instance number (0 to count-1) is set. In dataset mode, the column names of the dataset are expected to match the public properties of the template, and are set from each row.
  3. Template canvas. This sets the public properties of the selected templates from the “parameters” column of its dataset. The customizer helps set that up.

The repeater and the canvas don’t have any other mechanism to bind to the properties of the templates. You must arrange for the templates’ internal bindings (private properties and components) to interact with the rest of the system based on the above.

1 Like

Yeah we are on the same page for template properties. I use many templates and template repeaters with dynamically bound properties. In this situation there are overlapping template repeaters with rows that occupy in the same space, and based on configuration of a UDT, blocks of rows will be displayed from each repeater.

Whew! You're a glutton for punishment. I'd just use the template canvas to place the correct template in each space.

so there is no way to deploy template canvas in a template canvas with some properties?
i have canvas with 100 childs. Every child is a template with canvas with 100 other childs.
I dont want to do it manually, but i'm failing to do it programmatically