How do I use the Input, Output, Input/Output options on perspective's view params?

I am attempting to create a confirmation dialogue in perspective. I need it to popup, ask the user if they are certain they want to take this action, and then give them the option to say yes or no. I am uncertain how I can retrieve their response from the view that called the confirmation dialogue. I suspect it has something to do with the input, output, input/output param options but I can’t seem to find any resources on how to use them. Can someone please explain how these are used or where resources are that explain it?
Capture

2 Likes

I would also really like to be able to use this if anyone has any insight on it.

Popups are a little unique in how they use params, so I’ll cover both Popups and Embedded Views.

First:
Views will allow you to configure “input”/“output”/“input/output” params. The Designer has no way of knowing how you’re going to use the View down the road, so we don’t prevent you from configuring in any of those ways.

Input params can not be bound TO any value, but other values can be bound to them. They are read ONCE - during the View’s construction phase, and then they are essentially ignored, outside of your own references.
Output Params will ignore any incoming value at construction time, but Embedded Views can make use of this param (EmbeddedView.props.params['my_output_param_key']) to read values you’d like to send out.
Input/Output params are a two-way communication to allow for seamless communication between the View, the Embedded View component, and the View which the Embedded View component contains.

Popups:
Now, this is where Popups are a bit different. If a View with an Embedded View has root.FlexContainer.EmbeddedView.props.params as a property, then reading that value is easy; Popups are NOT attached to a View (this is a very important concept), so there is no way to reference any form of output param (although input params are used by the popup during its construction phase).

If you have a value you want to get out of a popup, you have two options:

  1. Set a session property based off of some action in the popup.
  2. Send a message from the Popup using system.perspective.sendMessage(), and then configure a listener in the View which invoked the Popup.
1 Like

So to actually use the params in an Embedded View use-case:

  1. Create a small View called “MyViewA” (200px x 200px should work).
  2. Place a Numeric Entry Field component in this View, along with a Button.
  3. configure two params for the View, my_input and my_output.
  4. Bind the Numeric Entry Field to self.view.params.my_input.
  5. Configure an onClick Event for the Button which executes a Script Action with the following code: self.getSibling('NumericEntryField').props.value = self.getSibling('NumericEntryField').props.value + 1
  6. Bind the my_output param to self.root.getChild(‘NumericEntryField’).props.value.
  7. Place a Label into MyViewA, and bind Label.props.text to self.view.params.my_output
  8. Make a new View called “MyViewB” and place an Embedded View component in this new View.
  9. Supply the path to “MyViewA” for EmbeddedView.props.path.
  10. For EmbeddedView.props.params, you will need to provide a case-sensitive key for both my_input and my_output, and you can go ahead and supply a value for my_input.
  11. You could supply a value for my_output, but you’ll see that the Label in “MyViewA” doesn’t display any value if you do so, while your label in “MyViewB” will.
  12. In MyViewB, place a Label component.
  13. Bind Label.props.text to EmbeddedView.props.params.my_output.
  14. Save, then place your Designer into preview mode.
  15. Note that the Numeric Entry Field is displaying your my_input param.
  16. Clicking the button should increment the Numeric Entry Field, and since your my_output param is bound to that value, you should see the change in MyViewB.
1 Like

Good explanation Cody,

I am curious in terms of logic when using popups and sendMessage. If you use sendMessage, that requires you to separate your code into multiple sections, you would have your “onClick” script calling the popup, then a sendMessage script on your popup calling back to your main view, then a messageHandler script to perform the action.

This would essentially force you to split your overall procedure into three different sections, on the event, in a sendMessage, and in a message handler.

If you were able to collect that output parameter when the popup closed (like in a vision dialogbox) than you would be able to have your entire section of code in one place, overall making a much cleaner scripting experience.

You're able to do that in Vision because Java/Swing lets you make truly modal popups - while a dialog box is open, the main event loop is literally paused waiting for it to close. Modals on that level aren't possible in web browsers outside of something like alert(), which is totally locked from appearance customization and has a host of other problems: W3Schools Tryit Editor

Would it be possible to use prompt() the same way?
https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_prompt

True, but while some would view that as a "con", it can also be viewed as a "pro": while you're forced to split your code into three separate areas, you can make all three areas as generic as you need to use them across countless instances.

You very literally only need to make one ConfirmationDialog View in your global project, pass it the relevant params, allow the Popup to send a generic DIALOGCONFIRM messageType with a boolean value, and then you never need to make another confirmation view across your entire project.

That works for a boolean, but in the event of an input dialog you would need to make separate messageTypes for each would you not?

For instance here, you have two “add to list” buttons that would call a dialog box, then wait for response and add them to the list.

You would have to have a separate messageHandler for each, and call them separately from the perspective (:wink:) of the input box.

Technically I guess you could pass it the name of the messageHandler as well, but then you still have code in 5 different places for two buttons.

Yes and no - if you design smart, then you can turn those two input areas into one parameterized View which is just rendered differently based on a passed parameter.

Please don’t think that I don’t see what you’re saying, but part of moving into Perspective is about doing everything you can to build with already constructed pieces; anywhere you see yourself using something more than once, then you should consider looking into ways to make it a template, because you’re probably going to want to use it again later.

2 Likes

Excellent description! I had been designing all of my flexrepeaters to send a perspective message until this. The problem with that is you have to somehow identify that if you want to make a change to one instance in a flexrepeater you somehow have to send an identifier in the payload so the scripts knows which instance to act on. Using output params makes this significantly easier!

com.inductiveautomation.ignition.common.script.JythonExecException
Traceback (most recent call last):
File “function:runAction”, line 12, in runAction
ValueError: invalid literal for int() with base 10: ‘’

caused by org.python.core.PyException

Traceback (most recent call last):
File “function:runAction”, line 12, in runAction
ValueError: invalid literal for int() with base 10: ‘’

Ignition v8.1.9 (b2021080617)
Java: Azul Systems, Inc. 11.0.11

i am getting above error plz help …
as i have passed one view’s value to another popup view via scripting by creating params image
now the default string “value” is getting passed and not the values from main view button script
image
above is the popup screen, data should get retrieved from main view and should get saved aftr pressing on popup’s button “yes/proceed”
plz help


this is main view’s button script where i have added params as components of main view to get the values

ValueError: invalid literal for int() with base 10: ‘’

You're passing something that is not a valid int to something that expects one, somewhere in your code.

1 Like

You supplied the code which passes the params, but not the code which is actually failing, so we don’t know which param is failing. Please provide AT LEAST line 12 of the faulty code. One of your params is passing an empty string, which cannot be converted to an integer.

int("")
Traceback (most recent call last):
  File "<input>", line 1, in <module>
ValueError: invalid literal for int() with base 10: ''

You could either capture the error/exception in the faulty code, or change the default value to an integer. It’s worth noting that string to int conversion can fail if you pass decimal values, so you might want to cast as a float first.

int("2.5")
Traceback (most recent call last):
  File "<input>", line 1, in <module>
ValueError: invalid literal for int() with base 10: '2.5'
int(float("2.5"))
2
1 Like

thanks for your replies.

I was getting error only in console but in runtime no issues, it’s working on browser as params values are correctly passing as expected.

data is getting saved into database but I want to display the data in table component as well but table component is in main view that is view 1 so how can I use table.refreshBinding(“props.data”) in view 2 button event script? is any there solution for table to refresh after inserting data? do I need to follow same param procedure for table as well r any other way ?

There is no way for a view to reference any component in a different view. For cross-view communication, you will either need to use Message Handlers, or assign the value to a custom session property.

1 Like