Tab Strip Scripting and Binding

Hi all,

I am new to Ignition and scripting (and everything else). I am adding a Tab Strip to the project I am using to learn.

I have the Tab Strip bound to a Named Query that returns 2 columns. An id and a name.

Based on what I have read, it looks like scripting is pretty much limited to an event script. If there is a better way, please let me know.

I want to be able to do the following:

  1. Set the Tab names to the names in the names column of the query.

  2. Pass the id to a parameter or a value.

Is binding this to the query the right way to do this? The query dataset will be dynamic and I will want the Tab Strip to adjust accordingly.

I have read through a lot of previous post but I think many of them are beyond my current understanding.

What I do not see is a property for each tab to be able to see the names.

Any direction you can provide will be much appreciated.

Thanks, Steven

The ignition programming setup is event driven programming, you are correct on that. You only call scripts on events, whether the event is a tag change, a GUI interaction, or something else that is changing or causing an event.

If you make a fresh Tab Strip component, then click on the Tab Data to see what is currently there, you’ll see this

These are the columns you need to alias in your SQL SELECT clause which you’ll need bounnd to the Tab Data component.

Yes, binding to a SQL query I believe is the way for you to do this especially if you want it dynamic as you can set a SQL polling rate in the situation where you might have users manually changing items in the database that will change the tab appearance.

The important bit here is this - you need to SELECT something as tabPropertyName in your query. So just for the names of the queries you would need to do SELECT myDBColumn as NAME, otherDBColumn as DISPLAY_NAME, ... and in this instance, whatever your otherDBColumn value is is what the Tab will display. The NAME property I believe is used for the selected tab property on the tab strip.

Ignition offers a really good intro course I highly recommend going through either as needed or all at once if you have the time - Browse the Lesson Library at Inductive University

Also, their documentation is normally very good and has pages on their scripts as well as components.

@bkarabinchak.psi,

I never thought about it like that. So I can use event.source.tabData as the source table (or dataset in this case) in the query?

I will try to put this together and see what happens.

Thanks, Steven

Maybe I misunderstood.

What I am saying is that for your Tab Data property, it makes sense to bind it to a SQL query if you are basing it on a database table.

So you would bind Tab Data to a SQL Query Binding (or Named Query Binding if you already have one), but the important thing is that in your SQL Query or Named query, the columns you select MUST line up with the NAME, DISPLAY_NAME, ENABLED, etc, if you want the results of the query to affect the Tab Strip appearance. You can select additional columns but they won’t affect the Tab Strip appearance.

If your tabs are going to be static, you can also always right click on the tab strip -> customizers -> Tab Customizer, and then enter your tab strip information manually. In fact, perhaps do this for just a few of the tabs you are expecting, and then take a look at the Tab Data property data to see how it affects the columns. It might help illuminate things for you.

@bkarabinchak.psi,

I’m sorry, but I don’t understand. How do I get the dataset into a query?

I have a table (binder_topics) with 2 columns: id, topic_name. I want to use the topic_name in my dbtable as the Display_Name in the Tab Strip dataset.

Sorry but all this is very new to me.

Thanks, Steven

I think we need to start at the beginning. I have a meeting in about two minutes, but I can maybe help answer afterwards.

Is this going to the same named query, and just changing parameters?

@JordanCClark

I don't think so. I want be able to change the names on the tabs and output a value (which I dont think is an issue).

I am reading up on changing datasets now.

Thanks, Steven

@JordanCClark @bkarabinchak.psi,

So looking at Datasets, I cam up with this…

newData = system.dataset.setValue(event.source.tabData, 0, 1, “newName”)
event.source.tabData = newData

I put this in the property change event on the Tab Strip. It does change the name of the Display Name of row 0 and the remainder of the dataset remains the same. HOWEVER, Ignition Designer comes to a screeching halt and the Console window freezes up.

So something I am doing is not liked.

Thanks, Steven

Your property change event is firing itself, repeatedly; that’s what’s causing the lockup. Introduce a custom property running the query, and filter the property change event to that property’s name.

put the query in a custom property. Then in the propertyChange event:

if event.propertyName = 'whatever_you _call_your_custom_property':
    do_some_stuff

Looking for a specific property name will help you filter out unwanted events.

@PGriffith & @JordanCClark

Ok, so something like this?

In Custom Methods I can run the query to get the id and names.

topic_list = system.db.runNamedQuery(“topic_list”)

The in the property change, I can do this…

if event.propertyName = ‘topic_list’:
here I will modify the dataset and replace it.

so doing this, the property change will fire everytime the query is run, or changes?

I sure appreciate all the help!!

Thanks, Steven

Hi Steven, sorry for the late reply. The needs of production outweigh the needs of the forum. Or something like that.

I’m getting something written up for you. Still be a few minutes. :slight_smile:

@JordanCClark,

I guess I do not grasp the concept. I can capture the ‘selectedTab’ property in an if statement and can print the selected tab and the dataset each time the selectedTab changes.

But when I change the dataset in the if statement, it goes into the perpetual loop and freezes.

Just saw your message and I totally understand. Work always comes first and I would expect nothing less. Gives me lots of time to read and try stuff… :rofl: :rofl: :rofl:

Thanks, Steven

Ok here is something for you to play with. Import this into a fresh project so it doesn’t interfere with anything you have now.

JC_TabStrip_From_Query_2020-10-13_1145.zip (6.6 KB)

I added two custom properties to the tab strip.
image
topic_list is bound to the named query, also named topic_list


tabFormat, I just copied from the default tabData, and deleted all but one row. We’ll use this in a bit to craete the new tabData.

In the propertyChange event:

if event.propertyName == 'topic_list':
	# Get the tabstrip component. Since we will be referencing
	# it a lot, it's handy to create an easy reference.
	tabStrip = event.source
	# Get the PyDataSet version of topic_list
	topicDataSet = system.dataset.toPyDataSet(tabStrip.topic_list)
	# Get the pyDataSet version of the tab format
	formatDataSet = system.dataset.toPyDataSet(tabStrip.tabFormat)

	# Create format list. It's just everything after the
	# tab name and display name. This will get added to the id 
	# and topic from the topic list dataset 
	format = list(formatDataSet[0])[2:]

	# Get the tabData headers. It's why I kept all the columns
	# in for format dataset.	
	tabDataHeaders = list(formatDataSet.getColumnNames())
	dataOut = []

	# Iterate through the topics and add the format to it.
	for row in topicDataSet:
		dataOut.append(list(row) + format)
	
	# Write the new tabData
	tabStrip.tabData = system.dataset.toDataSet(tabDataHeaders, dataOut)
1 Like

@JordanCClark,

This is exactly the function I wanted. Now I understand the custom property. Each time the topic_list changes (or is opened and closed) it is seen as a property change and fires the event.

I know what is happening below, but do not understand how.

Where can I get more details on the list() function. The manual shows list but nothing this detailed.

Thanks so much!!!

Steven

This should be an okay start on python collections.

@JordanCClark,

ok, so we are making a list starting at index 2. However, what is the [0] for? I am assuming it is row 0 of formatDataSet. I did not see that in the Python tutorial or the Ignition manual.

Thanks, Steven

You are correct, sir!

This actually digs a bit deeper into the java classes for datasets and pyDataSets, but the upshot is that pyDataSets can use subscripts and make lists out of the rows, while normal (for lack of a better word) datasets cannot. For me, it's a matter of convenience. You could do the same thing without making it a pyDataSet and using a loop or list comprehension:

formatDataSet = tabStrip.tabFormat
format = [dataset.getValueAt(0,i) for i in range(2,formatDataSet.getColumnCount())]

-or-

formatDataSet = tabStrip.tabFormat
format=[]
for i in range(2,formatDataSet.getColumnCount()):
	format.append(dataset.getValueAt(0,i))

Personally, I prefer the subscripts as it's easier for me to read. More of a style preference, really, as each dataset type has its own set of useful features.

Hopefully, I didn't throw more mud in the water for you.

No Sir that is great!! I will work this into my project.

Again, thanks so much for the help and the resources.

Thanks, Steven

@JordanCClark so I ran into a problem when implementing the tab strip into my project.

The Selected Value of the tabstrip is a string. The query in my table expects an integer. As built, the Selected Value of the tab is actually a number because we use the topic.id(index) of the topic_name.

But because the datatype was a mismatch it would not work.

SO, I created another custom property on the tabstrip, named it selectedTabInt. I then added an expression to selectedTabInt using toInt({Root Container.Topic Tab Strip.selectedTab}, -1).

I then used selectedTabInt as the parameter in the query. Works great.

Thanks for the lesson!!

Steven

1 Like