Hi, How we can add a confirmation message with Toggle switch as we have with Required Confirm button.
Please edit to add the vision
or perspective
tag from the dropdown below your question title.
Can you explain how the user interface would work? Why a toggle switch rather than a momentary button? Can you post a nicely cropped screengrab?
Thanks for highligting the subject missing info.
Here i have to show a ON/OFF button first i tried "One Short Button" the shows the confirmation but i cant implement as i want.
No i want to use the Toggle Switch but by default there no confirmation option.
I have created a view for popup with YES and NO button. But can not do this also.
There is a problem with your approach. The Toggle Switch will turn on before the onActionPerformed event occurs.
If you want to do this, I suggest:
- Create a Confirm / Cancel dialog view that can be used anywhere in your program.
- Give it parameters. For example,
- Title (for optional titlebar on popup).
- User prompt. e.g. "Confirm switch on MANUAL mode?"
- Message handler name. You are going to need to to add a message handler to the MANUAL toggle switch to respond to the sendMessage passed back from the popup.
- On the Confirm button, right-click, Configure Events.
Script
def runAction(self, event):
msg = self.view.params.messageName
system.perspective.sendMessage(msg, {'confirm': True}, scope = 'page')
- Do the same on the Cancel button but set
{'confirm': False}
.
That should be all you need to do on the popup.
On the toggle switch:
- Add a custom property
confirmedSelected
. Set it tofalse
for now. This is the value your application will actually use - not theprops.selected
value which will change state before you have confirmed it. - On the toggle switch, right-click, Configure Scripts.
Script
def onMessageReceived(self, payload):
if payload['confirm']:
self.custom.confirmedSelected = True
else:
self.custom.confirmedSelected = False
self.props.selected = False
- system.perspective.sendMessage | Ignition User Manual
- Component Message Handlers | Ignition User Manual (Read the docs and watch the video.)
Remember, the MANUAL mode tag will be contolled by a binding to custom.confirmedSelected
(and not props.selected
).
Add the tag from the dropdown. (Don't type it out in the title. I fixed it.)
Disable the toggle switch and bind the the selected property to your bool without biderection. Create a custom property that contains the tag path as a string of the bool that you want to toggle and a parameter for the tag path on your popup window too. Then just put an event "OnClick" on the toggle, use the popup action , and pass your custom property to the popup's parameter. From there you can add a script binding on the "Yes" button to write to the tag specified by the tag path, and the "No" button simply closes the popup.
You will probably want to mess with the stylesheet for the toggle as by default, disabling it removes its color and changes its appearance. There's this post about changing the style of disabled objects. You can also change the pointer to something instead of the X with a custom style called "cursor: pointer"
Oooh! That's neater than my solution. I hadn't considered disabling the bidirection.
Here's a button that I made awhile ago that uses a one shot button and confirmation on both states... edit to suit your needs. Test thouroughly as I'm not sure if I ever used it.
Paste as JSON.
{
"custom": {},
"params": {
"confirmText0": "",
"confirmText1": "",
"enabled": true,
"fontSize": 14,
"style0": "operation-button-unselected",
"style1": "operation-button-selected",
"text0": "Text Off",
"text1": "Text On",
"writeValue": false
},
"propConfig": {
"params.confirmText0": {
"paramDirection": "input",
"persistent": true
},
"params.confirmText1": {
"paramDirection": "input",
"persistent": true
},
"params.enabled": {
"paramDirection": "input",
"persistent": true
},
"params.fontSize": {
"paramDirection": "input",
"persistent": true
},
"params.style0": {
"paramDirection": "input",
"persistent": true
},
"params.style1": {
"paramDirection": "input",
"persistent": true
},
"params.text0": {
"paramDirection": "input",
"persistent": true
},
"params.text1": {
"paramDirection": "input",
"persistent": true
},
"params.writeValue": {
"paramDirection": "inout",
"persistent": true
}
},
"props": {
"defaultSize": {
"height": 50,
"width": 100
}
},
"root": {
"children": [
{
"meta": {
"name": "OneShotButton"
},
"position": {
"grow": 1
},
"propConfig": {
"props.confirm.enabled": {
"binding": {
"config": {
"expression": "if(\r\n\t{view.params.confirmText0} !\u003d \"\" \u0026\u0026 {view.params.writeValue} ||\r\n\t{view.params.confirmText1} !\u003d \"\" \u0026\u0026 !{view.params.writeValue},\r\n\r\ntrue, false)"
},
"type": "expr"
}
},
"props.confirm.text": {
"binding": {
"config": {
"expression": "if({view.params.writeValue},\r\n{view.params.confirmText0}, {view.params.confirmText1})"
},
"type": "expr"
}
},
"props.enabled": {
"binding": {
"config": {
"path": "view.params.enabled"
},
"type": "property"
}
},
"props.readyState.text": {
"binding": {
"config": {
"expression": "if({view.params.writeValue},\r\n{view.params.text1}, {view.params.text0})"
},
"type": "expr"
}
},
"props.setValue": {
"binding": {
"config": {
"expression": "!{view.params.writeValue}"
},
"type": "expr"
}
},
"props.style.classes": {
"binding": {
"config": {
"expression": "if({view.params.writeValue},\r\n{view.params.style1}, {view.params.style0})"
},
"type": "expr"
},
"persistent": true
},
"props.style.fontSize": {
"binding": {
"config": {
"path": "view.params.fontSize"
},
"type": "property"
}
},
"props.value": {
"binding": {
"config": {
"bidirectional": true,
"path": "view.params.writeValue"
},
"type": "property"
}
}
},
"props": {
"confirm": {},
"readyState": {
"icon": {
"style": {
"height": "24px",
"width": "2rem"
}
}
},
"style": {
"classes": "operation-button-unselected",
"whiteSpace": "pre-wrap"
},
"writingState": {
"icon": {
"style": {
"height": "24px",
"width": "2rem"
}
},
"text": ""
}
},
"type": "ia.input.oneshotbutton"
}
],
"meta": {
"name": "root"
},
"props": {
"direction": "column"
},
"type": "ia.container.flex"
}
}
There's always a million ways to accomplish the same task in Ignition, I love seeing others solutions and taking a crack at it. Your solution is certainly explained a lot better than mine and easier to follow along!
I do wish Perspective had some sort of built in confirmation function like Vision does, I've used it quite extensively. My solution is based on how I normally would do a custom confirmation in Vision, where I want to see the actual button/toggle state at all times
I'm delighted that it does not. And I strongly encourage anyone using them in Vision to reconsider.
The entire post-action confirmation paradigm is broken. Where you have the urge to use it, instead leave that action component disabled, and control that enable from another button. In other words, require two clicks, but in the other order: permission, then action.
This reversal is particularly import when an action has timing constraints, and the popup to confirm screws up the user's action.
Just say NO to popup confirmation. Everywhere.
The one shot button has confirmation and I've used it for a lot of things where the client demanded a prompt. See my example I posted.
I see your point, however I'm not sold on the permissive / action idea quite yet as a replacement for confirmations. I have implemented similar function before, for example pressing 'Edit' as a permissive for recipes or pressing 'Control' for important process controls. But the thing that these are all missing are custom messages.
Confirmations I see as having 2 primary benefits:
- Preventing mis-inputs and proving intention
- Relaying the implication the action is about to have
Keep in mind, I'm by no means saying Vision's built in confirmation is the end all be all. I'd say I use a custom confirmation popup the majority of the time. But it seems your main issue is with any post-actions themselves.
99% of the time customers ask me to put confirmations on certain buttons because they keep accidentally clicking buttons around their intended button due to touchscreen is mis-calibrated. Does another permissive button solve the same problem? Sure. But now I'm doubling the amount of buttons on a possibly very cluttered control interface.
I don't mind. People are wrong on the internet all the time.
No, the cleanest solutions use one permissive button for all of those that need it. I usually put a timeout on it, too, and canceling on a 2nd touch.
For me, retaining visibility and liveness of all the other controls on a window/view precludes the use of popups on control interfaces.
one permissive button for all of those that need it
One permissive button still does not prevent you from then selecting the wrong action button.
I've seen this happen numerous times. Imagine a footer with 2 rows of 10 buttons closely together. All it takes is the screen calibration to be off or for an operator to fat finger the screen to select a button above / below the intended selection. With one permissive button this will not prevent this from happening. It just means you have an extra step before you press the wrong button.
I've heard stories from a customer of operators shutting down parts of a process because they meant to click a button above it.
And I've heard stories of similar customer outages because operators can't see what's happening while the popup is open and/or no longer read the popup text any more.
AFAIAC, the touchscreen calibration concern just means you bought a too-small touchscreen, or cheap [expletive], and you are getting what you paid for. Fix that.
Hope Industrial 19" touchscreen monitors are what the customer uses. They're used inside, outside, and in wet environments all at the same place. They drift over time, and I don't think you're going to get around that with any resistive touchscreen.
Accidentally pressing a button happens a lot more often than the off chance that popup covers important info. Especially in process / line control instead of fast paced machine control.
Plus the popup takes up such a small amount of screen real estate that its hard for me to imagine it covering much at all.
An operator wearing a glove that's wet or extra long fingernails shouldn't be the reason an entire process goes down. Confirmation buttons go on every button that has potential to immediately halt the line