Diving into nested templates and repeaters, is this right?

Continuing my journey into nested templates, origin point is this thread, but I did change the structure a little. My intent was to make it simpler, but I'm not sure if this is the right way to do it.

This is the lowest level template:
image

I have three of these inside another template with an additional button:
image

This template, then, is used inside a Template Repeater, currently three repeated instances, with a total of 19 instances.

Note: I did post pictures like these in my previous thread, but I have slightly different question this time with a slightly different structure.

With this code, I have found a way to read from the UDT on the lowest level template and write to it's components. (I think I got the Java or Python(?) class descriptors from a post by @justinedwards.jle )

repeater = event.source.parent.getComponent('Template Repeater 2')
templateList = repeater.getLoadedTemplates()
for template in templateList:
	for counter in range(3):
		for component in template.components:
		if 'TemplateHolder' in component.__class__.__name__:
			compDir = component
			print compDir.name # the name of each instance of the Recipe_Manager_Crystal_1
			if compDir.UDT.Control.ON_OFF == False:
				tempComp = compDir.getComponent(0) # The name of the template Recipe_Manager_Crystal_1					
				numObj = tempComp.getComponent(5)
				numObj.value = 10.0

Note: Don't mind the naming convention of some of those variables, I just reused them for different types/objects as I was going.

The end goal, here is to bring in a dataset of values to write to the Numeric Text Field (which is referenced by this: numObj = tempComp.getComponent(5), then allow the user to adjust said value using the +/- buttons, and finally write those values to each UDTs Control Value for the selected positions.

One thing I am not sure about is how to count the number of templates within another template, hence the counter in range(3). We will have templates with from two to four nested templates, so if there is a way to count the number of nested templates, I would love to learn it!

To re-posit the question: Is this code representing a good/right way of reading UDTs and writing to components in those lowest level nested templates, and the second part will this work to write to the UDTs? (Using writeBlocking(), of course.)

Vision is perfectly happy to let you drill up or down in any component hierarchy--there's no barriers to any introspection.

As for lengths--any variable-size content in any Vision component is driven by some kind of dataset, which has a .rowCount property, or directly by a repeat count. No need to use constants. And for cases where you want to iterate through a list (of templates perhaps), you can use python's enumerate() function to supply integers with the objects.

2 Likes

Instead of drilling down through the layers to pass values, I called Support and he helped me understand I could use the repeater.templateParams to pass values to the base layer templates.

That works well, however, the button in the middle layer, labeled "CZ01/02/02", needs to access and change some values in it's parent Template Repeater. So, I figured this much out:

obj = system.gui.getParentWindow(event).getRootContainer().getComponent('Template Repeater 2') # This works
params = system.dataset.toPyDataSet(obj.templateParams)
output = []
for row in range(params.getRowCount()):
	output = system.dataset.setValue(params, row, 5, 1)
    print output.getValueAt(row,5)

The print statement prints the correct value (1), seven times. But, when I add this line to the code:

obj.templateParams = output

I don't see seven one's. The only 1 I see is the last one, the other six values are unchanged.


Edit: I manually changed the first row values.

Ok, I think I see why: the setValue() function returns a new dataset every time it's called...

I found out how to get a dataset into a list, like so:

query = "Development/Recipe/ZoneNameList"
params = {}
results = system.db.runNamedQuery(query, params)
data = [[0] * results.getColumnCount() for _ in range(results.getRowCount())]
for i in range(results.getRowCount()):
	for j in range(results.getColumnCount()):
		data[i][j] = results[i][j]

Now, how do I take this list and set it as the new templateParams?

I figured that part out.

Now, I have two more questions:

  1. How do I get the second level template, in a repeater, to know which repeater it's in? If I could say If you're in repeater 1, else if you're in repeater 2... Because there are many zones in each repeater, and each zone has from one to four positions. I need to change specific zone-position properties.

To access these properties, via the template parameters on the repeater, this is what I have:

zone = event.source.parent.zone

obj = system.gui.getParentWindow(event).getRootContainer().getComponent('Template Repeater 2') # This works

row = params.getRowCount()
col = params.getColumnCount()
output = [[0] * col for _ in range(row)]
for row in range(row):
	for col in range(col):
		output[row][col] = params[row][col]

# Toggle the whole zone
if output[zone - 1][1] == 1:
	output[zone - 1][1] = 0
else:
	output[zone - 1][1] = 1

headers = params.getColumnNames()
headers2 = []
for item in headers:
	headers2.append(str(item))

outputDS = system.dataset.toDataSet(headers2, output)

obj.templateParams = outputDS

This code addresses changing the values in my second post, going from dataset to list and back to dataset for the templateParams. If this code does not know which repeater it is in, it won't be able to find it's zone number in the templateParams on the repeater, and won't be able to change the second field parameter value, in this case.

  1. How can I count the number of objects (whether templates or components) nested in a template? @pturmel mentioned .rowCount and repeat count but I have not been able to successfully apply .rowCount() to any object, yet. If I take the loaded templates from a repeater and print that, I get an array.
comp1 = event.source.parent.getComponent('Template Repeater')
comp1Objects = comp1.getLoadedTemplates()
print(comp1Objects)

What I would like to do is something like:

for template in templates:
   if parameter1 == 1:
      parameter2 = 0

This is why I used the for counter in range(3): in my original post, but like I said, there could be 1 to 4, not just 3. I am referring to the lowest level templates to loop through, and the code would need to exclude the button (which has a text like CZ01).