# Passing multiple values into a window as parameter

**URL:** <https://forum.inductiveautomation.com/t/passing-multiple-values-into-a-window-as-parameter/11229>\
**Category:** Ignition\
**Created:** [February 17, 2016, 9:00pm UTC](https://forum.inductiveautomation.com/t/passing-multiple-values-into-a-window-as-parameter/11229 "2016-02-17T21:00:15Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![karnick](https://avatars.discourse-cdn.com/v4/letter/k/c37758/32.png) [@karnick](https://forum.inductiveautomation.com/u/karnick)\
**Post date:** [February 17, 2016, 9:00pm UTC](https://forum.inductiveautomation.com/t/passing-multiple-values-into-a-window-as-parameter/11229/1 "2016-02-17T21:00:15Z")

</div>

Hi. I don’t think this currently exists, but part of my application requires going through a series of popup windows and sending data back and forth. Ideally, I would love to be able to create a python class and pass the object into the window and modify it along the way.

I know I could make a UDT, but I don’t want the data being shared across clients. Strictly local variables are what I would like, and I would like to do this without having to add a dynamic property to every window for every single value I want to use.

Open Screen1(and pass in myObj)

myObj.field1 = ‘abc’  
myObj.field2 = 123

Open Screen2(and pass in myObj)

myObj.field3 = 1

Open Screen3(and pass in myObj)

(access field1, field2, and field3 and do something)

Any ideas?

Thanks!

---

<div class="post-metadata">

**Author:** ![diat150](https://avatars.discourse-cdn.com/v4/letter/d/a587f6/32.png) [@diat150](https://forum.inductiveautomation.com/u/diat150)\
**Post date:** [February 17, 2016, 10:33pm UTC](https://forum.inductiveautomation.com/t/passing-multiple-values-into-a-window-as-parameter/11229/2 "2016-02-17T22:33:03Z")

</div>

why not a dataset?

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [February 17, 2016, 11:25pm UTC](https://forum.inductiveautomation.com/t/passing-multiple-values-into-a-window-as-parameter/11229/3 "2016-02-17T23:25:35Z")

</div>

Datasets are immutable, so that doesn't tie anything together.[quote="karnick"]Strictly local variables are what I would like, and I would like to do this without having to add a dynamic property to every window for every single value I want to use.[/quote]Well, you may need to add at least one . . .

> [@karnick](#):
>
> (access field1, field2, and field3 and do something)

It is possible to add custom properties to root containers and other components that don't fit the custom property editor's suggestions. In particular, you can add a property of type 'java.io.Serializable' and it will happily accept an assignment of a python dictionary. Assign that dictionary to properties in multiple windows and voila, you have a namespace shared across those windows (or components).  
Start by manually adding such a property to your windows using the Script Console:`from com.inductiveautomation.factorypmi.application.binding import DynamicPropertyDescriptor
import java.io.Serializable
dprop = DynamicPropertyDescriptor('MyAnything','Anything Serializable',java.io.Serializable,dict())
w = system.gui.getWindow('Main Window')
w.rootContainer.dynamicProps.put(dprop.name, dprop)`Make sure it's a new 'dprop' for each window! Then in event scripts you can assign the dictionary in one window to another.  
I haven't tested all of this (you read the warning above, right?), but be aware that propertyChange events won't fire when you add or remove dictionary items.

---

<div class="post-metadata">

**Author:** ![nmudge](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nmudge/32/3394_2.png) [@nmudge](https://forum.inductiveautomation.com/u/nmudge)\
**Post date:** [February 18, 2016, 12:29am UTC](https://forum.inductiveautomation.com/t/passing-multiple-values-into-a-window-as-parameter/11229/4 "2016-02-18T00:29:42Z")

</div>

Hello,

Phil’s suggestion will work in clients, but not in designers. The reason is because objects created with Python classes are unserialized differently than objects created with Java classes. So opening a window that has serialized Python objects will throw exceptions.

Using an object that is created with a Java class will work in designers and clients. Here’s an example using Java’s HashMap:

`from com.inductiveautomation.factorypmi.application.binding import DynamicPropertyDescriptor
import java.io.Serializable
from java.util import HashMap
dprop = DynamicPropertyDescriptor('MyAnything','Anything Serializable',java.io.Serializable,HashMap())
w = system.gui.getParentWindow(event)
w.rootContainer.dynamicProps.put(dprop.name, dprop)`  
I think it would be very good if Ignition supported Python dictionaries and Python lists as custom properties directly. If you think so then vote for this feature request: [ideas.inductiveautomation.com/fo … ists-as-cu](http://ideas.inductiveautomation.com/forums/255378-ignition-features-and-ideas/suggestions/12371676-support-python-dictionaries-and-python-lists-as-cu)

Best,

---

<div class="post-metadata">

**Author:** ![nminchin](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nminchin/32/6911_2.png) [@nminchin](https://forum.inductiveautomation.com/u/nminchin)\
**Post date:** [November 6, 2019, 2:17am UTC](https://forum.inductiveautomation.com/t/passing-multiple-values-into-a-window-as-parameter/11229/5 "2019-11-06T02:17:50Z")

</div>

This is rather old, but…  
Are python functions serialisable? I want to pass a function to a confirmation popup Window (the standard confirmation dialogue buttons are too small for operators to press on a touch screen) which I can then call if the operator presses “Yes” for example.

How would you actually use this code to pass something to another window?

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [November 6, 2019, 2:27am UTC](https://forum.inductiveautomation.com/t/passing-multiple-values-into-a-window-as-parameter/11229/6 "2019-11-06T02:27:58Z")

</div>

Try using .putClientProperty() to attach the callback function to the popup window. The buttons would extract them and call them. You’d probably need to construct the function as if for use with invokeLater–arguments captured in closures.

---

<div class="post-metadata">

**Author:** ![nminchin](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nminchin/32/6911_2.png) [@nminchin](https://forum.inductiveautomation.com/u/nminchin)\
**Post date:** [November 6, 2019, 2:40am UTC](https://forum.inductiveautomation.com/t/passing-multiple-values-into-a-window-as-parameter/11229/7 "2019-11-06T02:40:39Z")

</div>

Awesome! I got a simple `print "Hello Ignition"` working. Thanks Phil, as always 🙂

On button to call confirmation popup:

```auto
def fn():
	print 'Hello Ignition!'

window = system.nav.openWindow('Popups/ppuConfirmAction')
system.nav.centerWindow(window)

window.putClientProperty('functionOnYes', fn)

```

On ‘Yes’ button in confirmation popup window:

```auto
window = system.gui.getParentWindow(event)
fn = window.getClientProperty("functionOnYes")
fn()

```

To pass a parameter to use in the function however, I do this (same thing as required when you want to pass arguments into functions called from `system.gui.createPopupMenu`):

```auto
deviceTagPath = system.gui.getParentWindow(event).rootContainer.DeviceTagPath
	
def fnOnYes_create(deviceTagPath=deviceTagPath):
	def fnOnYes(deviceTagPath=deviceTagPath):
		system.tag.write(deviceTagPath + '/Run Time Reset CMD', 1)
	return fnOnYes

message = 'This will reset the runtime hours. Are you sure?'
shared.util.gui.confirmAction(event, message, fnOnYes_create())

```

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [November 6, 2019, 1:00pm UTC](https://forum.inductiveautomation.com/t/passing-multiple-values-into-a-window-as-parameter/11229/8 "2019-11-06T13:00:57Z")

</div>

If you spend some time learning about python closures, you’ll find that the machinations in the latter example aren’t really necessary… (:

---

<div class="post-metadata">

**Author:** ![nminchin](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nminchin/32/6911_2.png) [@nminchin](https://forum.inductiveautomation.com/u/nminchin)\
**Post date:** [November 6, 2019, 6:56pm UTC](https://forum.inductiveautomation.com/t/passing-multiple-values-into-a-window-as-parameter/11229/9 "2019-11-06T18:56:00Z")

</div>

Hmm, so I could use something like this instead? Could I go one step further and remove the create function’s argument as well? (can’t test at the moment, on phone) from what I read closures only work within nested functions, so I presume not

```auto
deviceTagPath = system.gui.getParentWindow(event).rootContainer.DeviceTagPath
	
def fnOnYes_create(deviceTagPath=deviceTagPath) :
	def fnOnYes():
		system.tag.write(deviceTagPath + '/Run Time Reset CMD', 1)
	return fnOnYes

message = 'This will reset the runtime hours. Are you sure?'
shared.util.gui.confirmAction(event, message, fnOnYes_create())

```

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [November 6, 2019, 7:05pm UTC](https://forum.inductiveautomation.com/t/passing-multiple-values-into-a-window-as-parameter/11229/10 "2019-11-06T19:05:57Z")

</div>

I’m guessing Phil means something more like this:

```auto
from functools import partial

deviceTagPath = system.gui.getParentWindow(event).rootContainer.DeviceTagPath

message = 'This will reset the runtime hours. Are you sure?'
shared.util.gui.confirmAction(event, message, partial(system.tag.write, deviceTagPath + '/Run Time Reset CMD', 1))

```

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [November 6, 2019, 7:28pm UTC](https://forum.inductiveautomation.com/t/passing-multiple-values-into-a-window-as-parameter/11229/11 "2019-11-06T19:28:06Z")

</div>

No, not at all. A function definition _captures_ variables in outer local scopes so long as they are explicitly used in the function. Captured at the point of definition. Put this in a button’s actionPerformed event:

```auto
logger = system.util.getLogger('SomeLogger')
def showEvent():
	logger.infof("Delayed event display: %s", event)

system.util.invokeLater(showEvent, 1000)

```

Put it in preview and click. You will see the event object printed on the console a second later. The `event` variable supplied as a local variable is included in showEvent’s _closure_. Along with `logger`. Simpler than explicitly defining function arguments and supplying them via partial. I generally don’t like using def in dynamic locations, as there appears to be a time penalty. But for passing arguments to spawned tasks, it is really readable–too convenient to not do.

(I converted later.py to this technique once I fully grokked it.)

---

<div class="post-metadata">

**Author:** ![nminchin](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nminchin/32/6911_2.png) [@nminchin](https://forum.inductiveautomation.com/u/nminchin)\
**Post date:** [November 6, 2019, 7:41pm UTC](https://forum.inductiveautomation.com/t/passing-multiple-values-into-a-window-as-parameter/11229/12 "2019-11-06T19:41:55Z")

</div>

Ohh, so I dont need the whole function-creating-function mechanic at all:

```auto
deviceTagPath = system.gui.getParentWindow(event).rootContainer.DeviceTagPath
	
def fnOnYes():
	system.tag.write(deviceTagPath + '/Run Time Reset CMD', 1)

message = 'This will reset the runtime hours. Are you sure?'
shared.util.gui.confirmAction(event, message, fnOnYes)

```
