Ignition has a wonderful component called a Template Repeater. The Template Repeater allows you to create dynamic displays using a single template as many times as your screen calls for. This is perfect if the number of objects you need to display can vary, or if the amount of objects is simply unknown.
The Template Repeater has a lot of support for funneling data into it and using indirect tag bindings to control the components inside of the template, but a reliable method for getting information out of the templates is not initially apparent. This can cause a problem when you need to create an unknown amount of text input fields, for example when the function of your page is to insert new rows into SQL tables and you need to create an input field for an unknown amount of columns. We’re going to address this issue by making use of Ignition’s Custom Properties and the getLoadedTemplates() method to create a new dataset property on a Template Repeater that provides a simple method of obtaining and storing data from templates inside of the component.
The whole process will take about 10 minutes and provide a solid foundation you can use to store any type of data you need from your templates in an much more accessible manner than is currently available.
Creating the Input Template
The first thing we are going to do is create a new template and add a few custom properties to it to store the information we want to retrieve, as well the information we need to link the template to the repeater.
In the Project Browser, right-click on “Templates” and select “New Template.”
Press “Ctrl+P” to bring up the Size & Position dialogue and set the templates height to 50px. This is to make sure the templates are displayed in a presentable manner in the repeater.
Click the customizer icon and add 3 custom properties: index, repeater, and value.
- index (Integer) – the index of the template inside of the Template Repeater component
- repeater (String) – The name of the Template Repeater component
- value (String) – The value we will be retrieving from the template inside of the Template Repeater
Drag a Label and a Text Field component onto the template, and align them within the template bounds using the vertical alignment tool to make your template look something like this:
Next we are going to bind the value of our label to display the index of the template in the template repeater. This is just to help us differentiate between the templates once they are loaded into the Template Repeater.
Click the binding icon on the Labels “Text” property, select the “Expression” binding type, and add the following line to the Expression:
Finally, we need to select our Text Field component, press “Ctrl+J” to bring up the Scripting dialogue and add the following propertyChange script to it:
if event.propertyName=="text": #if the property that changed is the 'text' property... window=system.gui.getParentWindow(event) #...get the window that triggered the event... if event.source.parent.repeater=="": #...if the 'repeater' property has not been defined... window.rootContainer.initRepeater() #...define the 'repeater' property... event.source.parent.value=event.newValue #...update the 'value' property... window.rootContainer.getComponent(event.source.parent.repeater).updateTemplates() #...update the Template Repeater's template dataset
This script updates the dataset we will define on the Template Repeater every time the text is changed.
The first line ensures that our script will only execute if the property that changed is the Text Fields “text” property. It’s a good practice when writing propertyChange methods to always check that the property you are working with is the property that triggered the method call.
The second line stores the window that the template is on when the propertyChange is triggered. This is going to let us access the custom methods we will be defining on that window and it’s components.
The next two lines check to see if the “repeater” property of the template has been set, and set the property if it has not using the initRepeater() method that we will define in the next section. This will set the “repeater” property on the template to match the Template Repeaters name property.
Finally we update the “value” property we defined earlier with the new value and call the updateTemplates() method on the Template Repeater this instance is displayed on.
Now that the template is created we are ready to move on.
Configuring The Template Repeater
Now that we have our input template set up, it’s time to configure our Template Repeater. In the Project Browser right-click on “Windows” and select “Main Window” to create a new main window.
Next, drag a Template Repeater and a Table component onto the window and resize them appropriately. With the Template Repeater selected click the customizer icon and add a new Dataset property named “templates” to the component.
Then change the “Template Path” property to point to the InputTemplate we just created and set the “Count” property to your favorite number. I’m going with 7, but you can go with the number 23, 117 or the answer to life the universe and everything, 42, and it will still work just the same.
With the Template Repeater selected press “Ctrl+J” to bring up the Scripting dialogue and add two new custom methods to the component: initTemplates() and updateTemplates()
- initTemplates() – set the “repeater” property of each template in the Template Repeater
- updateTemplates() – create a dataset containing the template values
Let’s take a look at the code.
templates=self.getLoadedTemplates() #get the loaded templates from Template Repeater for template in templates: #iterate through the templates template.repeater=self.name #set the current templates 'repeater' value to the Template Repeater's name property self.updateTemplates() #update the 'templates' dataset
This method is pretty straightforward. It goes into each template in the repeater and sets the custom ‘repeater’ property that we defined earlier to the Template Repeater’s name property. This is so we can have multiple template’s and repeaters on a page and still update the correct Template Repeater’s values when the Text Field is edited.
templates=self.getLoadedTemplates() #get the loaded templates from Template Repeater headers=["index","value"] #define the 'templates' dataset column names body= #declare the 'templates' dataset's data list for template in templates: #iterate through the templates body.append([template.index, template.value]) #append the current templates 'index' and 'value' properties to the 'templates' dataset's data self.templates=system.dataset.toDataSet(headers, body) #update the 'templates' dataset with the new data
This method will create a new dataset out of the properties we defined in the template and store them in the ‘templates’ dataset on the Template Repeater.
The first line stores a list of the templates inside of the Template Repeater.
The next two lines are used to define the data in the dataset. The “headers” list will store all of the column names for the dataset, and the “body” will contain a list of lists that will make up the body of the dataset.
The two lines following that iterate through the templates and add a list containing the “index” and “value” properties of each template as a row in the ‘templates’ dataset.
The last line creates the actual dataset and assigns the value directly to the ‘templates’ dataset. We are now almost ready to use the Template Repeater.
The last method we need to define is the initRepeater() method. this method is going to be called on the main widow by the uninitialized Text Field in the template to define it’s “repeater” property so it can directly update it’s parent Template Repeater. It’s a very simple one line of code:
This method finds the template repeater by name and calls the initTemplates() method. To add multiple input Template Repeaters to a single page simply duplicate this line and change “Template Repeater” to match your second Template Repeater’s name.
Finally, we are going to bind the Table components “Data” property to the “templates” dataset we’ve just defined by clicking the Binding icon next to the “Data” property, selecting the Property binding type and using the tree view to selecting the “templates” property of the Template Repeater.
If we put the designer in Preview Mode (F5) and edit the Text Field of the template we will see now that the table will display the dataset of index/value pairs we just defined.
Congratulations! You made it to the end and you have just added a new convenient way to store and access your data inside of a Template Repeater in Ignition. Lets review the important parts one more time:
- We utilized the getLoadedTemplates() method to access templates in a Template Repeater
- We utilized Custom Properties and Methods
- We established communication between a Template and a Vision Component in an external Window
- We created a more accessible way to utilize data from a Template Repeater
This framework can store any amount of data you may want to store by simply creating a new custom property on the template and updating the following lines in the updateTemplates() method to include the new property:
headers=["index","value","newProperty"] body.append([template.index, template.value, template.newProperty])
Thanks for reading, if you found this tutorial helpful subscribe to our blog for more Ignition tips, tricks, tutorials and projects. It only takes two seconds, it’s free and it helps us out a lot. If you have any questions, comments or concerns we would love to hear from you. Leave a comment below or contact us any time @ http://www.perfectabstractions.com/contact.html.