Passing reference to component to a window

I have made a few template components that I want to attach a popup to that will return the value for the template component.

I am currently handling this through the click event on the instance of the template on a screen. Each popup has a ParentWindow and a ParentComponent custom property. The popup uses this information to write the value back to the component that spawned it. This only works for components in the root container as I did not see a way to find a component on a window only given the window path and component name.

This method works fine, but the click event of each instance placed on a window must be configured. The best place to place this functionality is in the component. There are challenges, however.

The first challenge, how to get the parent screen without passing it in? I am sure I could get parent until I reached the top level, then get the path.

Next challenge is not really a challenge, as it is easy to get the component name. However, it would really be nice to have a property or function that returns a path to the component from the root container. By just using the component name, my method of getting to the component from the popup is limited to components in the root container.

The third challenge is also not really a challenge. Having the path to the component allows us to set the appropriate property. Since I am using each popup for a specific custom component, I know what property that is. If this was general use, then property names could be an issue.

Most of this would be solved by the ability to pass a component reference to a screen. I do not know if this can be done, I did not see a datatype in the custom properties that seemed like it would work.

Unless I find something else, I will likely just add the ParentWindow and ParentComponent properties to my components, I just felt that there should be a cleaner way to do something like this.

What is your popup actually doing? Can you not handle the tag interaction in the popup instead of passing it to the Template? Ie pass the path to the tag to the popup and use bindings in the popup to the tagpath to read and write to it

I’m copy pasting my personal notes, but perhaps you’ll find them useful.
Here:

Using callbacks in Vision

Window - Caller

  • Can be in the script of a button.
  • The callback can reference event or self depending on the context in which this script is running (within a custom method, or a component event).
def callback():
	print 'hey'

window = system.nav.openWindowInstance('Popups/popupName')
window.putClientProperty('callback', callback)
system.nav.centerWindow(window)

Popup - Callback

window = system.gui.getParentWindow(event)
callback = window.getClientProperty("callback")
callback()

Questions

  • What happens if client property isn’t defined? I think it just returns None.
  • What happens if calling window isn’t opened anymore?
    • Use weakref(s) if that’s a concern.

Using weakref

Note:
Weakref is a python module to add to folder user-lib\pylib of Ignition:
It avoids breaking garbage collection in some cases.

# -----------------
# DUBEG:
# For whatever reason, the weakref must be created
# within a built-in component event (eg. propertyChange, actionPerformed), 
# and not within a custom/extension method, otherwise it won't work (weakref returns None).
# Not sure why, but probably related to the way extension methods are handled.
# You can always pass the callback function as an argument to a custom method, and that will work.
# -----------------
import weakref

textbox = event.source.parent.getComponent('tbResult')
textboxRef = weakref.ref(textbox)

def callback():
	o = textboxRef()
	if o is not None:
		o.text = "Callback :)"

window = system.nav.openWindowInstance('Popups/ppuConfirmAction')
window.putClientProperty('callback', callback)
system.nav.centerWindow(window)
1 Like

Not everything has a tag. Sometimes I am using the screen components to hold values until they are saved. Some of the stuff comes from a field in a dataset. The popup is just a means for the user to provide a value for a component.

The ideal solution is providing return parameters

1 Like

Thanks for the reply, i will take a closer look at this when I get a chance.

@gdube shows how to use store arbitrary functions in Swing client properties. You can also stick a different window’s component in one. Like you asked.

Got this to work. Thank you for the suggestion.

Glad you found a solution.

I have found though that most of the time just using a container inside the window that looks like a popup, is suitable to most situations and eliminates the entire problem as the parent window can access anything within the container (and vice versa).

1 Like

That gets messy if there are several popups. Also would have to do that on every screen that needed the popup.

It’s not suitable for all instances, like for a popup that could be called from a multiple of windows/spots, it makes much more sense to make a completely separate popup. Though you could get around this with a template.

If it’s only every possibly called from a single window - I think it makes thing’s a bit cleaner.

But to each their own. No “right” way to do this.