VisionWindowOpened Script fires on designer update

Every time I push a designer update to my clients the VisionWindowOpened Script fires causing problems with my application. Is there a way to stop that script from running after an update or an update flag I could use to not run my code after the application has been updated?

Thanks

Lee

Is there anything about the setup that you can check in that script?
Lets say you set up a dataset in your script, you could check if that dataset’s rowCount is higher than zero, if so don’t run the setup script.

I’m afraid your best bet will be to alter your application logic in order to work around this. From our perspective, this behavior is correct. Fundamentally, your window is closing and re-opening as part of the update (this is how the update actually gets a chance to apply any changes to the window)

It makes sense that there is a event which fires whenever the window is opened (including when updating the project). However, I think we also need another event (or a flag which can be read from visionWindowOpened) which will only run when a window is opened with system.nav.openWindow, and not when the project is updated.

The reason this is necessary is because there are actually two kinds of Root Container properties:

  1. Properties expected to be passed in to system.nav.openWindow
  2. Internal state properties stored on the Root Container

Usually, internal state properties need to be initialised when the window is opened, to set the window into a clean state.

However, if the project is reloaded, the internal state properties need to be preserved. If we make sure all the important state is stored in root container properties like this (and not within other component properties), the user will not lose their current state when the project is updated.

There are two ways to workaround this, but they are both horrible:

  1. Create a project function which takes external properties as arguments, does any extra initialisation for internal properties and then passes the whole lot to system.nav.openWindow. This is horrible because window initialisation code is now stored outside of the window.
  2. Add an additional property to the window to track whether the window has been opened or not. This is horrible because it’s supposed to be an internal property, but it has to be passed to system.nav.openWindow to reset it every time.

Please could we have either another event, or a flag available from visionWindowOpened so we can handle this properly?

Thanks.

I’ve come up with a workaround for this, but it’s not ideal.

We have a project.nav.openWindow function like this:

def openWindow(path, params=None):
    if params is None:
        params = {}

    window = system.nav.openWindow(path, params)
    if callable(getattr(window, 'runOnce', None)):
        window.runOnce()

Now you can define a ‘runOnce’ custom function on the window, and it will be run when the window is opened, and not when the project is updated.

However, we still need this to be implemented properly in Ignition. This solution is only a temporary workaround - it’s not ideal, because:

  1. You have to make sure you always open windows with project.nav.openWindow, and never use system.nav.openWindow directly
  2. runOnce is called after visionWindowOpened. I think it’s more likely you would want it to run before, to set some properties which visionWindowOpened then uses.

Perhaps the better solution for implementing this properly in Ignition would be to have a flag available in visionWindowOpened which we can use to check if we’re opening for the first time or for a project update. This would allow us to cover the before and after cases easily, and avoids the confusion of two similar events.

Consider using client tags to hold your application’s global state instead of window root container properties.

I’m not sure how that makes any difference to this issue?

The problem is about where the state is initialised, not where it is stored. If you initialise the state in visionWindowOpened, it doesn’t matter whether you store it in client tags or in root container properties. Because visionWindowOpened runs again when the project is updated, the state will be overwritten.

If you initialise the state before opening the window (and either store it in client tags or pass it as root properties to the window) then everything is fine. But this requires the code to be stored outside the window, which isn’t really desirable when it’s so intrinsically linked to the window.

Initialize the state of the client tags in the designer only. The client will open the first time with the saved values.

That’s definitely not what we are talking about here. We’re talking about loading data in the client, e.g. opening a window to edit a record. If you load the record from the database in visionWindowOpened, then it will be reloaded from the database if the project is updated.

So if the project is updated whilst someone has the form open, it reloads the record and blows away their changes.

Similarly, if you do some sort of check and show a warning message in visionWindowOpened, if the project is updated the warning will be shown again.