I’m working on dynamically updating a tag path within a Flex Repeater every time a new instance is created.
I have two views:
Repeated View: Contains a label and an “Increase” button.
Flex Repeater Test: Repeats the “Repeated View.”
Currently, the label in each repeated instance displays a tag associated with its index (e.g., “Row 1/Total” for the first instance, “Row 2/Total” for the second).
I'm aiming to modify the button’s behavior so that, when pressed, it increments the corresponding total in the tag path. For instance, clicking the “Increase” button in the second instance would increase the value associated with “Row 2/Total.”
[Uploading: image.png…]()
# Retrieve the dynamic tag path from the view parameters
tag_path = self.view.params.tagPath
print "tag_path result:"
# Read the current tag value
current_value = system.tag.readBlocking([tag_path])[0].value
# Increment the tag value
new_value = current_value + 1
# Write the new value back to the tag
system.tag.writeBlocking([tag_path], [new_value])
# Optional debugging output
system.perspective.print("Incremented {} to {}".format(tag_path, new_value))
This is the code within the "add row" event:
# Get the Flex Repeater component
repeater = self.getSibling("FlexRepeater")
# Get the current list of rows (instances)
current_rows = repeater.props.instances
# Get the row number for the new row (after appending)
row_number = len(current_rows) + 1 # Adding 1 because row_number is 1-based
# Construct the dynamic tag path based on the row number
tag_path = "[default]Flex Repeat test/Row {}/Total".format(row_number)
print "Hello, Ignition!"
# Read the current tag value
current_tag_value = system.tag.readBlocking([tag_path])[0].value
# Debugging: Print the constructed tag path and current tag value
system.perspective.print("Tag Path: {}".format(tag_path))
system.perspective.print("Current Value of {}: {}".format(tag_path, current_tag_value))
# Define a new row with label, value, and tagPath set to the current tag path and value
new_row = {
"label": str(current_tag_value),
"value": current_tag_value,
"tagPath": tag_path # Adding tagPath to each instance
}
# Append the new row to the list
current_rows.append(new_row)
# Set the updated list back to the Flex Repeater
repeater.props.instances = current_rows
# Force UI update by reassigning the instances property
repeater.props.instances = list(current_rows)
# Debugging: Print the updated rows
system.perspective.print("After Adding: {}".format(current_rows))
Your repeated view has tagpaths as a parameter, not tagpath.
Also, consider only passing the tag path to the repeated view and using that to make an indirect bidirectional binding to a custom property on the view. Then you can just increment that property's value by the desired amount and it will be pushed to the associated tag, no need to call tag.write* or tag.read*.
Right now you are passing the repeated view the tag path and the tag's value(I assume) so you can display it.
Instead, create a custom property on the repeated view and indirectly bind to the tag using the tagPath parameter. Make sure the binding is bidirectional.
Because you are using a bidirectional binding on the tagValue property, whenever it receives a new value from something other than the tag, it will write the new value back to the tag automatically.
This also lets your simplify your "add row" script a bit:
# Get the Flex Repeater component
repeater = self.getSibling("FlexRepeater")
# Get the current list of rows (instances)
current_rows = repeater.props.instances
# Get the row number for the new row (after appending)
row_number = len(current_rows) + 1 # Adding 1 because row_number is 1-based
# Construct the dynamic tag path based on the row number
tag_path = "[default]Flex Repeat test/Row {}/Total".format(row_number)
print "Hello, Ignition!"
# Debugging: Print the constructed tag path
system.perspective.print("Tag Path: {}".format(tag_path))
# Append the new row to the list
current_rows.append({"tagPath": tag_path})
# Set the updated list back to the Flex Repeater
repeater.props.instances = list(current_rows)
# Debugging: Print the updated rows
system.perspective.print("After Adding: {}".format(current_rows))
Right, becasue in my current setup with the code I provided in the begining, the tag tree value updates when button is pressed but not the value in the label.
Correct, because you essentially passed a snapshot of the tag value when you created the instance. Without any additional code or process to pass in the new value, it will stay the same as when you created the instance.
So in your image showing the binding setup, it looks like you are passing an instance number, but in the final picture you are passing the entire tag path. Look at the value of 'tagpath' in your instances property of the flex repeater.
With the indirect binding you have configured you are passing [default]Flex Repeat Test /Row [default]Flex Repeat Test/Row x /Total/Total instead of [default]Flex Repeat Test/Row x /Total hence the error binding to a tag.
If you are going to be passing the full tag path to the repeated view, then just have {tagPath} as the entire indirect bind path. Your flex repeater appears to be set up to pass the full tag path, so this will be the fastest.
It should be the same as
My example has an error because my tag path param is empty. Also, when building your example view, have an expected tag path in view.params.tagPath, it will make testing easier. In your case, have something like [default]Flex Repeater test/Row 1/Total
Also, I'm not sure if it matters but I typically use {1}, {2}, etc for indirect path references.
To be clear, your current issue stems from the fact that you are building the repeated view using an index value like 1 as the value for tag path when designing the view and testing the bindings, but when you are using the view in the flex repeater you are passing the full tag path.
One additional piece of advice for UDTs is to pass only the path to the UDT, and use that path to indirectly bind the UDT members that you need to custom properties on the view. You can then toggle visibility of certain fields based on which properties were able to bind to tag.
This lets you use one view with mutliple UDTs that have some members in common. Think a motor control where the most basic motor has start/stop/status, but another might have start/stop/status/rpm/rpmSetpoint.