Message sending failing between views

I have a simple script running on an "onRowClick" event on a table in my main view that gets the value of the row clicked, sets a tag equal to its value, sends a message to a different component on a different view, and then navigates to that view.

def runAction(self, event):
	import time.sleep as sleep
	data = system.dataset.toPyDataSet(self.props.data)
	system.tag.writeAsync(['[default]ShippingTags/OrderNum'], data[event.rowIndex])	
	sleep(1)
	message = "buildstring"
	system.perspective.sendMessage(message, scope = "session")
	system.perspective.navigate(view = "TicketScan")

The table that receives the message is configured as follows:

While the "onRowClick" event is definitely triggering (as the tag value is updated everytime) for some reason the message doesn't get sent every time. it works fine in the designer, but on the perspective mobile app the message script only seems to run rarely and without any particular pattern.

Any ideas on what could be causing this?

Taking a step back from your specific question - because you're writing to a tag, I want to make you super-aware that this could cause you issues because tags are globally scoped. Sometimes, that's exactly what you want, but in your case, what happens if there are two users on that page that has the Table and are both clicking rows? What about 3+ users? Then, the behavior seems undefined, at best.

In this section of code, why not remove time.sleep and just do a system.tag.writeBlocking call to your OrderNum tag, provided you even want to have an OrderNum tag?

I think this is where the problem arises. Perspective Message Handlers are asynchronous, which is okay in some situations but I think is the main problem you have (especially when you mention that the issues are seemingly random). Your sendMessage call gets put into a queue or buffer somewhere (probably) and there is no guarantee of the order of execution.

I think there are two possibilities of what is happening based on what you describe:

a. The sendMessage call is made before the navigate function is called, and because the TicketScan view is not open yet, the message essentially gets ignored. You can probably test this in a desktop browser by having a tab open with your TicketScan view and a tab open with your Table view. Since you're sending a session scoped message, I believe that should work.

~OR~

b. Some other funky combination of order of execution. For instance, the message gets sent after the view gets navigated to, but before the TicketScan view's Table loads its data (so your message script does get executed, but since len(self.props.data) is 0, you would never know).

If you describe your application more (and possibly give a few screenshots), we may be able to help you come up with a better design so that your events are consistent.

1 Like

Would it not just be easier to call the new view with the parameters you need to populate the table? For instance, send the order number to a parameter on the new view, then when the view loads, it uses that order number to populate the table? My other question would also be as @flexware noted, is that eliminates one tag write, but you have 2 others that may not be necessary depending on what you're trying to do with this data. If this data is being pulled from a database, you might be able to craft the SQL query to return the data pre-formatted for you into the table or a tag. We just need to know what you're trying to do to make sure you're doing it properly. (There may be multiple ways of achieving this, but using sleep timers is almost always a bad idea/decision)

Thanks for all that info, I'm relatively new to ignition and this is my first real project after watching through the inductive university videos, so I'm sure a lot of this project isn't exactly best practice at the moment. Ill try to answer your questions to the best of my ability.

You make a good point about why i should not be using a tag for the Order number, i had tried using session properties as well as view parameters to pass the value into the second table, but i could never get either to work so i went back to using a tag.

I added a sleep line into the code because i seemed to be having some weird condition (maybe the same type that is causing the current issue) where, once i clicked on an order number, it would update the order number tag, but not the corresponding LotList and LotConfirm tags in the message script. Once i clicked on a second order number, it would then update all 3 tags, but the LotList and LotConfirm will have the values for the order i had previously clicked on. This resulted in those two tags always being one selection behind what was clicked. Putting in a sleep command seems to have fixed that.

Basically the whole goal of the app is to have a screen with active orders in a table. When a user clicks on one of the active orders, it then shows a list of all the items for that order. After that, the user needs to scan tickets on the shop floor that have the corresponding items on them to make sure all items are accounted for. Once all items have been scanned in, the app will send a signal for us to do some more work unrelated to the app itself.

I did try doing this, but maybe i was setting it up wrong. On my "TicketScan" view, i have a single input param called "OrderNum"

I tried changing my "onRowClick" event to something like this:

def runAction(self, event):
	data = system.dataset.toPyDataSet(self.props.data)
	system.tag.writeBlocking(['[default]ShippingTags/OrderNum'], data[event.rowIndex])	
	system.perspective.navigate(view = "TicketScan", params = {'OrderNum':data[event.rowIndex]})

But it doesn't seem to ever change the value in the designer. Am i setting this up wrong in some way?

In designer you won't see this value change when a user clicks it because each user session will be private/unique, but if you use preview mode, I would think it should populate fine when clicking the button, but it's been a while since I've done some perspective work as I've been in Vision a lot lately. A quick way to test would be to throw a label on the screen bound to this parameter so you can visually see the value when on a client session to verify it's working.

Ah it looks like your right. I was testing it in preview mode, but maybe because i have to manually change views it resets the parameter since it also turns off preview mode. Once i added a label and tested it by running the actual app, it was displaying the number clicked on.

I'll do some configuring from here and hopefully I can get it running more smoothly. Thanks!

So, it looks like the parameter number is being passed in with brackets around the number. the table itself only contains the value as '262606' but after clicking on the row the label with the parameter is showing as '[262606]' which is messing up the table binding as the where clause is expecting a number after all.
Is this something to do with the table being converted to a pydataset and referencing by index number? This is the entire script now:

def runAction(self, event):
	data = system.dataset.toPyDataSet(self.props.data)
	system.perspective.navigate(view = "TicketScan", params = {'OrderNum':data[event.rowIndex]})

What's is the OrderNum column name?

You could replace the script with a one liner:

def runAction(self, event):
	system.perspective.navigate(view="TicketScan", params = {"OrderNum": event.value.ColumnName})

Replace ColumnName with the column's name in your dataset and that should work for you.

Perfect, that worked like a charm, thank you!

1 Like