Since the beginning of MainUI this question has cropped up with some regularity: Can I trigger more than one of the OH widget actions on a component with a single click?
The answer has always, rightly, been: No, you can only define a single action for each component in a widget.
This answer is not 100% true, there are ugly hacks that could allow a click on a link, for example, to trigger the actions of other components, but these are not truly supported nor even advised.
The question (and default answer) came up yet again the other day and I finally found it so unsatisfying that I decided to do something about it. I was looking at the MainUI code trying to decide what the best implementation might be when it occurred to me that there is already a native implementation that should work with just a little css. We just have to change the question to Can I trigger, with a single click, multiple components that each have an action?
The solution takes advantage of the
pointer-events css property which allows us to disable an element’s response to mouse clicks and the fact that a click event on a child element will propagate back up the document hierarchy to the ancestor elements. Put simply, if we nest a series of components and ensure that only the lowest element receives the click event all the other components get that event as well.
In practice it looks something like this:
- component: oh-link config: action: variable actionVariable: exampleVariable actionVariableValue: NewValue style: pointer-events: none slots: default: - component: oh-link config: text: Link for multiple actions action: command actionCommand: ON actionItem: SomeSwitchItem style: pointer-events: auto
This will appear on the widget as only a single link:
because the top link only contains the bottom link and so is sized to the same width and height as the bottom link.
The top link, however, has
pointer-events: none so it does not receive any of mouse interactions; instead, those get passed through to the bottom link. The bottom link has
pointer-events reset to
auto (if you do not specify this, it just inherits
none from its parent) so, the bottom link can receive mouse interactions. When it does, its click event is triggered which initiates the
command action, but that click event also propagates up the hierarchy and so the parent’s variable action is also initiated. Two actions for one click.
There aren’t really that many situations where this should be necessary. If you find yourself in a situation with your custom widget where you think you need this solution, you should carefully examine whether or not there is a better way. Nine times out of ten there probably will be. If you’re sending the same command to multiple different items then maybe it’s easier to put them in a group and send a single command to the group. If you’re sending different commands to multiple different items then maybe it’s just easier to trigger a rule. If you’re setting more than one variable then maybe it’s easier to make that variable an object with multiple keys. It’s not even sensible to try and open more than one modal at a time.
In real usage, the most likely place this is required is if you have a situation where you need to set a new value for a widget variable and also some other action simultaneously (combining an action and clearing one or more variable values can already be done).