# Open Popup from a Popup

**URL:** <https://forum.inductiveautomation.com/t/open-popup-from-a-popup/76270>\
**Category:** Ignition\
**Tags:** perspective\
**Created:** [July 12, 2023, 4:54pm UTC](https://forum.inductiveautomation.com/t/open-popup-from-a-popup/76270 "2023-07-12T16:54:11Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![Kawsar\_Ahmed](https://avatars.discourse-cdn.com/v4/letter/k/8797f3/32.png) [@Kawsar\_Ahmed](https://forum.inductiveautomation.com/u/Kawsar_Ahmed)\
**Post date:** [July 12, 2023, 4:54pm UTC](https://forum.inductiveautomation.com/t/open-popup-from-a-popup/76270/1 "2023-07-12T16:54:11Z")

</div>

I am working on a popup that will insert data into a database. However prior to storing the data, I would like the script to ensure that all the required fields are filled, and if so the user will need to validate their credentials to prior to the data being inserted into the database. However, I am having trouble with the system.perspective.openPopup function. When I run the script I get the following error on the openPopup line: AttributeError: 'com.inductiveautomation.ignition.designer.gui.tool' object has no attribute 'perspective'

```auto
def runAction(self, event):
	UDT = self.parent.parent.getChild("UDTFlex").getChild("UDT").props.value
	Asset = self.parent.parent.getChild("AssetIDFlex").getChild("Asset").props.value
	Users = self.parent.parent.getChild("OperatorsFlex").getChild("Users").props.value
	Supervisor = self.session.props.auth.user.userName
	Campaign = self.parent.parent.getChild("CampaignID").props.text
	Batchid = self.parent.parent.getChild("BatchID").props.text
	startTime = system.date.now()
	
	AssetS = str(Asset)
	UDTS = str(UDT)
	OperatorsS = str(Operators)
	SupervisorS = str(Supervisor)
	CampaignS = str(Campaign)
	BatchidS = str(Batchid)
	startTimeS = systeme.date.format(startTime, "yyyy-MM-dd HH:mm:ss")
	
	if UDTS == "" or AssetS == "" or OperatorsS == "":
		system.perspective.openPopup('empfieldsPopup', 'empfieldsPopup', showCloseIcon = True, pageID = 'addUDTpopup')
	else:
		system.perspective.openPopup('authPopup', 'authPopup')
	
	query = "INSERT INTO udtSelect (Asset, UDT, Operators, Supervisor, Campaign, Batchid, startTime) Values(?,?,?,?,?,?,?)"
	args = [AssetS, UDTS, OperatorsS, SupervisorS, CampaignS, BatchidS, startTimeS]
	system.db.runPrepUpdate(query,args)
	system.perspective.sendMessage("refresh", "session")
	system.perspective.closePopup('addUDTpopup')

```

This script is configured on the submit button of the currently opened popup

EDIT: I got the popups to open correctly. There were some minor typos and references preventing the script to run up to the if statement.

However, I want the script to update the database only after the authentication is successful, but I am unsure how to refer to the result of the authPopup into this script.

---

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [July 12, 2023, 5:29pm UTC](https://forum.inductiveautomation.com/t/open-popup-from-a-popup/76270/2 "2023-07-12T17:29:16Z")

</div>

Put a message handler on the root of the popup, and pass a message to that handler from the authentication popup, with the auth status in the payload.  
Grab all your required data and perform the database inserts from this handler instead of the button script.

Or get rid of the popups and use [system.perspective.authenticationChallenge - Ignition User Manual 8.1 - Ignition Documentation](https://docs.inductiveautomation.com/display/DOC81/system.perspective.authenticationChallenge)

---

<div class="post-metadata">

**Author:** ![Kawsar\_Ahmed](https://avatars.discourse-cdn.com/v4/letter/k/8797f3/32.png) [@Kawsar\_Ahmed](https://forum.inductiveautomation.com/u/Kawsar_Ahmed)\
**Post date:** [July 12, 2023, 6:54pm UTC](https://forum.inductiveautomation.com/t/open-popup-from-a-popup/76270/3 "2023-07-12T18:54:40Z")

</div>

I rewrote the script on the button to invoke and authentication challenge as shown below:

```auto
def runAction(self, event):
	UDT = self.parent.parent.getChild("UDTFlex").getChild("UDT").props.value
	Asset = self.parent.parent.getChild("AssetIDFlex").getChild("Asset").props.value
	Users = self.parent.parent.getChild("OperatorsFlex").getChild("Users").props.value
	Supervisor = self.session.props.auth.user.userName
	Campaign = self.parent.parent.getChild("CampaignID").props.text
	Batchid = self.parent.parent.getChild("BatchID").props.text
	startTime = system.date.now()
	
	AssetS = str(Asset)
	UDTS = str(UDT)
	UsersS = 'Kawsar' ##str(Users)
	SupervisorS = str(Supervisor)
	CampaignS = str(Campaign)
	BatchidS = str(Batchid)
	startTimeS = system.date.format(startTime, "yyyy-MM-dd HH:mm:ss")
	
	if UDTS == "" or AssetS == "": ## or UsersS == "":
		system.perspective.openPopup('empfieldsPopup', 'empfieldsPopup', showCloseIcon = True)
	else:
		system.perspective.authenticationChallenge(timeout = 5, payload = {"isAction":"true"})

```

I then configured the following on the session events for the authentication challenge:

```auto
def onAuthChallengeCompleted(session, payload, result):
	if result.isSuccess():
		system.perspective.sendMessage('loginSuccess', 'session')
	else:
		system.perspective.openPopup('incpassPopup', 'incpassPopup')

```

I then created a message handler on the root of the popup called "loginSuccess":

```auto
UDT = self.parent.parent.getChild("UDTFlex").getChild("UDT").props.value
	Asset = self.parent.parent.getChild("AssetIDFlex").getChild("Asset").props.value
	Users = self.parent.parent.getChild("OperatorsFlex").getChild("Users").props.value
	Supervisor = self.session.props.auth.user.userName
	Campaign = self.parent.parent.getChild("CampaignID").props.text
	Batchid = self.parent.parent.getChild("BatchID").props.text
	startTime = system.date.now()
		
	AssetS = str(Asset)
	UDTS = str(UDT)
	UsersS = "Kawsar" ##str(Users)
	SupervisorS = str(Supervisor)
	CampaignS = str(Campaign)
	BatchidS = str(Batchid)
	startTimeS = system.date.format(startTime, "yyyy-MM-dd HH:mm:ss")
		
	query = "INSERT INTO udtSelect (Asset, UDT, Operators, Supervisor, Campaign, Batchid, startTime) Values(?,?,?,?,?,?,?)"
	args = [AssetS, UDTS, OperatorsS, SupervisorS, CampaignS, BatchidS, startTimeS]
	system.db.runPrepUpdate(query,args)
	system.perspective.sendMessage("refresh", "session")
	system.perspective.closePopup('addUDTpopup')

```

This message handler should retrieve the values from the popup again and store said values into the database, which should then send a message to the table on the main page to refresh the table with the new database values.

I am now running into the following error on the session events: `com.inductiveautomation.ignition.common.script.JythonExecException: Traceback (most recent call last): File "", line 3, in onAuthChallengeCompleted at com.inductiveautomation.perspective.gateway.script.AbstractScriptingFunctions.lambda$operateOnPage$0(AbstractScriptingFunctions.java:64) at com.inductiveautomation.perspective.gateway.script.AbstractScriptingFunctions.operateOnSession(AbstractScriptingFunctions.java:120) at com.inductiveautomation.perspective.gateway.script.AbstractScriptingFunctions.operateOnPage(AbstractScriptingFunctions.java:47) at com.inductiveautomation.perspective.gateway.script.PerspectiveScriptingFunctions.sendMessage(PerspectiveScriptingFunctions.java:749) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.base/java.lang.reflect.Method.invoke(Unknown Source) java.lang.IllegalArgumentException: java.lang.IllegalArgumentException: No perspective page attached to this thread`

I believe this is saying that the sendMessage function is unable to determine which page to send the message so it therefore requires a pageID, but I am not sure how to pass the pageID of a popup. Should the payload of the authentication challenge on the button be the pageID of the popup? Do popups even have pageIDs since they are not configured pages with URLs?

---

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [July 12, 2023, 8:18pm UTC](https://forum.inductiveautomation.com/t/open-popup-from-a-popup/76270/4 "2023-07-12T20:18:26Z")

</div>

> [@pascal.fragnoud](#):
>
> Or **get rid of the popups** and use [system.perspective.authenticationChallenge - Ignition User Manual 8.1 - Ignition Documentation](https://docs.inductiveautomation.com/display/DOC81/system.perspective.authenticationChallenge)

disclaimer: I've never used the auth challenge.  
But mixing it up with popups looks to me like a snake pit.

---

<div class="post-metadata">

**Author:** ![Usman\_Ashraf](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/usman_ashraf/32/43168_2.png) [@Usman\_Ashraf](https://forum.inductiveautomation.com/u/Usman_Ashraf)\
**Post date:** [July 12, 2023, 9:08pm UTC](https://forum.inductiveautomation.com/t/open-popup-from-a-popup/76270/5 "2023-07-12T21:08:47Z")

</div>

Hey @Kawsar_Ahmed

If MH is on the root of the popup, then ideally the scope of the message handler should be page level, but `system.perspective.authenticationChallenge` opens a new tab, so the trigger will not have the access to the popup as it is a session level trigger.

One quick patch, will be to bind these values to Session Custom properties, then set the MH in Project \> Session Events \> Message, and this MH will have access to the Session object. And now the session object has custom properties which are bound with the page level components and their values.

It will be worth a try.

---

<div class="post-metadata">

**Author:** ![Kawsar\_Ahmed](https://avatars.discourse-cdn.com/v4/letter/k/8797f3/32.png) [@Kawsar\_Ahmed](https://forum.inductiveautomation.com/u/Kawsar_Ahmed)\
**Post date:** [July 13, 2023, 7:23pm UTC](https://forum.inductiveautomation.com/t/open-popup-from-a-popup/76270/6 "2023-07-13T19:23:25Z")

</div>

So I have configured it to trigger it an authentication event which sends a system level message which then sends a message to the popup to store the data into the database as shown below. However I am now getting a "Websocket disconnected from the session" error.

Script on button to trigger authentication challenge:

```auto
def runAction(self, event):
	UDT = self.parent.parent.getChild("UDTFlex").getChild("UDT").props.value
	Asset = self.parent.parent.getChild("AssetIDFlex").getChild("Asset").props.value
	Users = self.parent.parent.getChild("OperatorsFlex").getChild("Users").props.value
	Supervisor = self.session.props.auth.user.userName
	Campaign = self.parent.parent.getChild("CampaignID").props.text
	Batchid = self.parent.parent.getChild("BatchID").props.text
	startTime = system.date.now()
	
	AssetS = str(Asset)
	UDTS = str(UDT)
	UsersS = 'Kawsar' ##str(Users)
	SupervisorS = str(Supervisor)
	CampaignS = str(Campaign)
	BatchidS = str(Batchid)
	startTimeS = system.date.format(startTime, "yyyy-MM-dd HH:mm:ss")
	
	if UDTS == "" or AssetS == "": ## or UsersS == "":
		system.perspective.openPopup('empfieldsPopup', 'empfieldsPopup', showCloseIcon = True)
	else:
		system.perspective.authenticationChallenge(timeout = 5, payload = {'pageID':self.page.id})

```

Authentication Challenge Session Event:

```auto
def onAuthChallengeCompleted(session, payload, result):
	if result.isSuccess():
		system.perspective.sendMessage('loginSuccess', scope = 'session')
	else:
		system.perspective.openPopup('incpassPopup', 'incpassPopup')

```

Message on session event:

```auto
def handleMessage(session, payload):
	system.perspective.sendMessage('storeData', scope = 'session')

```

Message on popup root container to store data:

```auto
def onMessageReceived(self, payload):
	UDT = self.parent.parent.getChild("UDTFlex").getChild("UDT").props.value
	Asset = self.parent.parent.getChild("AssetIDFlex").getChild("Asset").props.value
	Users = self.parent.parent.getChild("OperatorsFlex").getChild("Users").props.value
	Supervisor = self.session.props.auth.user.userName
	Campaign = self.parent.parent.getChild("CampaignID").props.text
	Batchid = self.parent.parent.getChild("BatchID").props.text
	startTime = system.date.now()
		
	AssetS = str(Asset)
	UDTS = str(UDT)
	UsersS = "Kawsar" ##str(Users)
	SupervisorS = str(Supervisor)
	CampaignS = str(Campaign)
	BatchidS = str(Batchid)
	startTimeS = system.date.format(startTime, "yyyy-MM-dd HH:mm:ss")
		
	query = "INSERT INTO udtSelect (Asset, UDT, Operators, Supervisor, Campaign, Batchid, startTime) Values(?,?,?,?,?,?,?)"
	args = [AssetS, UDTS, OperatorsS, SupervisorS, CampaignS, BatchidS, startTimeS]
	system.db.runPrepUpdate(query,args)
	system.perspective.sendMessage("refresh", "session")
	system.perspective.closePopup('addUDTpopup')

```

Also, this method of bouncing messages around seems to be a little extreme to me, there must be a more concise method to this correct?

---

<div class="post-metadata">

**Author:** ![ryan.white](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/ryan.white/32/73193_2.png) [@ryan.white](https://forum.inductiveautomation.com/u/ryan.white)\
**Post date:** [July 13, 2023, 8:56pm UTC](https://forum.inductiveautomation.com/t/open-popup-from-a-popup/76270/7 "2023-07-13T20:56:49Z")

</div>

Pull the pageID from the popup with `self.page.props.pageId` (you have `self.page.id`?). There are some optional arguments for [system.perspective.sendMessage](https://docs.inductiveautomation.com/display/DOC81/system.perspective.sendMessage), `pageId` being one of them. The message send call in the Auth Event handler should be `system.perspective.sendMessage('storeData', scope='session', pageId=payload['pageID'])`

After that, change the message handler on the popup root container to listen at session level.

Mildly off topic but I would recommend putting a custom object called 'data' in the root container's custom properties(or the view custom properties), and have the items 'UDT', 'Asset', 'Users', 'Campaign', and 'Batchid' in it. Bidirectionally bind the associated entry fields to their respective keys in this object.

Then when you go to pull the data (or pass it in a payload) you can just pull `self.view.getChild("root").custom.data` and pass that wherever or assign it to a variable in the script. It would also allow you to use a custom boolean prop `okayToSubmit` with a binding that checks if `UDT` or `Asset` is blank. You would then only have to check this boolean in your button event script, turning it into a 4 line script.

---

<div class="post-metadata">

**Author:** ![Kawsar\_Ahmed](https://avatars.discourse-cdn.com/v4/letter/k/8797f3/32.png) [@Kawsar\_Ahmed](https://forum.inductiveautomation.com/u/Kawsar_Ahmed)\
**Post date:** [July 18, 2023, 3:17pm UTC](https://forum.inductiveautomation.com/t/open-popup-from-a-popup/76270/8 "2023-07-18T15:17:04Z")

</div>

I have implemented this, but for some reason I am getting a "websocket disconnected from session" error every time I attempt to execute. Also, how would this work with additional auth challenges on other pages? Would I just make all the message handlers have the same name and use the pageID to ensure the message is sent to the correct page?

---

<div class="post-metadata">

**Author:** ![ryan.white](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/ryan.white/32/73193_2.png) [@ryan.white](https://forum.inductiveautomation.com/u/ryan.white)\
**Post date:** [July 18, 2023, 6:27pm UTC](https://forum.inductiveautomation.com/t/open-popup-from-a-popup/76270/9 "2023-07-18T18:27:16Z")

</div>

The websocket disconnect is strange, I would recommend that you reach out to support with that, there might be something else interfering . Are you getting that error when you are testing in the designer or in a normal perspective session?

Since you are having to pass a pageID to be able to send a message back to the page that initiated the challenge, you can probably get away with relying on a handler on each page with the expected logic in it for a successful auth challenge.

If you are going to have multiple things on the same page calling an auth challenge with different expected process/data flows, you will want to add a 'sourceID' key to your payload as a way of identifying what called the auth challenge, and then have your page based handlers check that to determine what to do with the passed data.

At some point it will get cumbersome to have handlers on every page, so I would recommend having all your data handling logic in the auth challenge handler itself, and then have that report back to the page that called it (either opening a success popup or something similar and closing the original popup). If there is a lot of data processing or other logic, put it into a project level function and call that from the auth challenge handler.

---

<div class="post-metadata">

**Author:** ![Kawsar\_Ahmed](https://avatars.discourse-cdn.com/v4/letter/k/8797f3/32.png) [@Kawsar\_Ahmed](https://forum.inductiveautomation.com/u/Kawsar_Ahmed)\
**Post date:** [August 16, 2023, 8:19pm UTC](https://forum.inductiveautomation.com/t/open-popup-from-a-popup/76270/10 "2023-08-16T20:19:26Z")

</div>

I finally solved the issue. At first I thought the problem was that triggering the authentication challenge as scripted above was causing the page to reload, which led to a loss of the values I wanted to store. However, I tried to alleviate this by writing the values to memory tag prior to the authentication challenge, and upon success of the challenge the message handler on the root container would retrieve the values from the memory tags and would process them as needed. However this did not work. The values would write to the memory tags prior to the auth challenge, but the auth challenge failed to execute the message handler upon success.

I found that the issue has something to do with the auth challenge reloading the page maybe disconnecting the session for a second and terminating the auth challenge prematurely, hence the websocket error mentioned above. However, I cannot be certain that this is the root cause.

However I did find that having the popup open as an embedded frame did not reload the session and worked at completing the sequence of events I desired. See code and picture below.

```auto
system.perspective.authenticationChallenge(timeout = 5, framing = "Embedded", payload = {'pageID':self.page.props.pageId})	

```

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/5/9/59293489b13caeb7935af21bacebc63501176ed5.png)
