For Loop to Populate Leaflet Map in Perspective

Hello!
I have a bit of web-dev background but I'm new to Ignition and new to industrial automation. I'm currently trying to build out a list of station points in a Leaflet module inside a perspective view. To test this, I was able to go through and manually (one by one) associate the latitude, longitude, and the popup content text fields with their respective tags for the station (basically: [default]station/$x/$x_latlong, and [default]station/$x/$x_Name where $x is the name code for the station). In the screenshot below, you can see that I've used the unique station code as the name property for the current position in the ui.marker tree.

What I'm trying to do is find a consistent way to build out this map that doesn't rely on me having to duplicate a bunch of code or text (since this increases the risk of human error). By reading the documentation, I've figured out that I can reference that code in an expression to get the full tag:

tag("[default]LS/"+{this.props.layers.ui.marker[0].name}+"/"+{this.props.layers.ui.marker[0].name}+"_latlong")

...but this still requires me to define the specific name property instead of referencing it's own position. I'd like to simplify that further to something like this (where $x is the current position in the ui marker tree...

tag("[default]LS/"+{this.props.layers.ui.marker[$x].name}+"/"+{this.props.layers.ui.marker[$x].name}+"_latlong")

or (in my own imagined pseudo-code):

tag("[default]LS/"+{~.name}+"/"+{~.name}+"_latlong")

NOTE: I also have some expression and/or jython code that splits the above string and converts the output to a double/float value that leaflet understands, however I didn't want to complicate this post with those details since they are working properly.

Again, I'm trying to simplify this expression code so that it's self referencing the required unique station identifier and tag properties and placing them into the Leaflet widget. If I was doing this in HTML/JavaScript/PHP/etc, I'd define an array and a few variables, write out a for-loop to dump those values into the leaflet code as the page loads, then proceed on my way, but I don't see any kind of equivalent in Ignition which means I'm manually clicking and associating these values with their correct tags. This feels like the wrong way to do this, but I know I'm too new to this to know better. I've been Googl'ing all morning but haven't found much besides what I've already laid out.

Thanks for your time. Please let me know if I've come about this the wrong way and if there's a better way to use this system. I'm trying to learn and improve our operations at the same time.

The best way to do this is to bind the root of the array property, and use a script or @pturmel's (free) Integration Toolkit module provided expressions to construct all the items in sequence.

E.g. you could use an expression binding returning the number of elements, then iterate them via a script transform. There should be lots of examples of this available on the forums.

Like Paul said, you should start by creating a binding on your "marker" array. This is where you can do the same thing you mention with PHP and design some kind of transformation that creates everything for you in an iterative fashion. Bind it to something that, when its value refreshes, your list of instances should also refresh. Your bindings on lat and lng would have to be "coalesced" up into this larger binding if you move forward with this, such that they are fed down into the instance by the main "marker" binding transformation rather than themselves having these bindings.

At the end of the transform, you will need to return a list of instances in the order you so desire. You can accomplish this in many ways during your transformation.

[{name: BELA, properties:{yourPropertiesInHere}, enabled:True, lat: 42.75599, ......},{name: NextInstanceNameHere, properties:{NextPropertiesHere}...}...]

1 Like

Thanks for the help with this. I went through today and wrote a jython for loop as follows:

' for i in value[0:-1]:
name = i
#lat = "[default]LS/"+i+"/"+i+"_latlong"
#lat = lat.split(",")
fullName = "[default]LS/"+i+"/"+i+"_Name"
output = output + "name: " + name + ", enabled:True, lat: " + lat +", lng: "+", popup:{enabled: true, content:{text: "+ fullName+"}}}]"`

When I input the list of station identifiers, that seems to produces an output with the proper tag names and layout to populate the leaflet app:

' [{name: BELA, enabled:True, lat: [default]LS/BELA/BELA_latlong, lng: popup:{enabled: true, content:{text: [default]LS/BELA/BELA_Name}}}]'

However in the Perspective Property Editor, I am seeing an error that reads, "string found, array expected". I looked through the list of available expression functions (and google) to see if there's a way to convert this kind of string to an array data type, but I haven't found anything.

Is there something obvious I'm missing here? Do I need to have my jython code lookup the tag values directly? It's not immediately clear how to do that since the script section of the binding window only shows a button to add properties to this code.

Thanks again for your consideration.

You need to return an actual Python list, not a string.