Hi, I seem to be running into a road block with picking up form data. The issue is finding the sibling or child, when the form is dynamic (if this is possible at run time?)
This form and it drop down data is completely dynamic using flex repeaters and templates.
The issue is getting the form data for the submit button as seen below:
def runAction(self, event):
array = self.view.params.queryData
dictArray = dict(array)
if not isinstance(dictArray, dict):
system.perspective.print("Error: queryData is not a dictionary")
return
params = {}
for name, field_type in dictArray.items():
try:
if field_type == "dropdown":
value = None if self.getSibling('FlexContainer').getChild('dropdownRepeaters').getChild('root/'+name).props.value == "" else self.getSibling('FlexContainer').getChild('dropdownRepeaters').getChild('root/'+name).props.value
elif field_type == "text":
value = self.getSibling('FlexContainer').getChild('root/'+name).props.text
params[name] = value
except Exception as e:
system.perspective.print("Could not go through eaceh loop item: {}".format(e))
The line that says "value = None if..." seems wrong. You probably just want the if statement.
You can definitely dynamically generate forms and even bind them to tags.
You might want to create a tag structure that your form dynamically binds tags to. Then you can see the real time selected value very easily. Tags are easy to work with.
Here's some code from a screen I wrote that reads tags related to the I/O modules in a PLC and dynamically generates an instance of an I/O status template within a template repeater. This code lives inside a template to display the I/O points for a module in the PLC. Another view dynamically populates its template repeater with instances of this template to display I/O for each card in the PLC. You can really go crazy with dynamic binding.
You don't need to do it quite this complicated but the general idea is to use JSON to bind the newly created template instance to a tag binding. In this case it's creating instances for each tag within a folder in the tagdb and resizing the UI when it's done because this particular screen is sometimes used on mobile. The actual tag binding is done with an indirect binding on the template.
def transform(self, value, quality, timestamp):
descList = system.tag.browse(value + '/IO_Description', {})
returnList = []
i = -1
for x in descList:
i += 1
returnList.append(
{
"instanceStyle": {
"classes": ""
},
"instancePosition": {},
"Label": x["fullPath"],
"Index": i,
"TagPath": value
})
# Resize the screen based on the dynamic content that just got generated
# This is to kill white space when there are varrying numbers of IO points in a block
# IO points displayed are determined by the number of description tags in the tagdb
self.view.props.defaultSize.height = ((i + 1) * 30) + 40
return returnList
The line that says "value = None if..." seems wrong. You probably just want the if statement.
That has to be that way for the SQL insert, as that field can be Null, but a "" which is what the form sends when nothing is selected, is not null, and errors the sql insert
Instead of trying to scan the "value" of each child, is there a reason you're not populating some custom dictionary with the value from each component as part of an onChange script? This would make it so that you can just pull expected values from a dictionary (and make None-type defaults) instead of trying to determine child presence or structure.
Make a custom object at the View level, and then each component should just write to a unique key of the dictionary in an onChange script.