In the widget the action is hardwired to “analyze”. Is it possible to override this for a single instance of the widget in the instance’s YAML configuration? Or do I have to change the widget itself to allow users to set different actions? I tried to just add the action and actionUrl to the YAML of one widget instance, but it seems to be ignored, it still goes to analyze. Is this not possible, or am I just doing it wrong?
You could, of course, just use widget expressions with props, but that gets out of hand quickly, because many of the action options have their own specific settings and you would have to account for each one of those with a different property.and widget expression. Fortunately, there’s an intentional, built-in, fairly clever way to do this.
The shortcut is to include a parameterGoup in the widget header info with an action context. If you do that, then your widget config popup will include the default OH action configuration section which allows your user to configure the action type and all the required sub settings as usual.
To get that information into your widget, you also give that parameterGroup a name and then set that name as the actionPropsParameterGroup of the component that should perform that action. You don’t even need to directly configure any of the action properties for that component, it’s all taken care of by the actionPropsParameterGroup.
Take a look at my confirm button widget to see an example of this in action:
Yes, but it’s kind of obscure (also, more hack than intentional feature, I would guess).
There’s a lot going on in the background when you use the action parameter group, but it boils down to the fact that a series of values are automatically generated that match the required action with a prefix added that is the name you gave the group. So internally, if you have an action parameter group that you’ve named 'buttonPress' then there is a value buttonPress_action that holds the action type the user has selected in the configuration window.
This is important knowledge for two reasons:
it means we can configure a widget that has an action parameter group in the text editor instead of having to use the configuration wizard. For example, this could be used to configure the confirm button widget linked to above (the action parameter group is named confirmed):
component: widget:jag_confim_button
config:
confirmed_action: toggle
confirmed_actionCommand: ON
confirmed_actionCommandAlt: OFF
confirmed_actionItem: SomeItemName
text: Confirm item toggle
it means that we can actually override these properties by defining regular props in the widget with those names, and we can add default values to defined props. So if you just create a text property of groupname_action with a default value of 'analyzer' then your action parameter group will have a value for the action even if the user hasn’t opened up the configuration wizard and set one manually yet. Wash, rinse, repeat for each of the action values that you want to have default values for.
The one extra piece here is that if you create those props they will show up in the configuration wizard which will be confusing for users because they will just be duplicates of the action inputs in that same wizard. You can easily hide all these extra props however by giving them some other group name and then not defining that group under the widget’s parameterGroups. For instance, I like to use groupName: hidden.
Altogether it looks like this. If you have this action parameter group:
That does not seem to work for me. I have first tried to create the group customAction with context=action. If I set an action there, it works and the widget executes that action. However I tried to use the action value as header just for testing with “props.customAction_action” but that remains undefined. If I define hidden props with that name (commented out in the example below) then “props.customAction_action” does have a value, but it does not define the action. The action is still empty if not set explicitly in the configuration UI.
Did I get something wrong about how to name these generated properties?
uid: TemperatureHumidity
tags:
- humidity
- standalone
- temperature
props:
parameters:
- description: Title of the cell.
label: Title
name: title
required: true
type: TEXT
groupName: title
- context: item
description: The state of this item will be displayed as temperature.
label: Temperature item
name: tmp_item
required: true
type: TEXT
groupName: items
- context: item
description: The state of this item will be displayed as humidity.
label: Humidity item
name: hum_item
required: true
type: TEXT
groupName: items
- context: item
description: The display state of this item will be displayed as last update
timestamp. Use an item with the timestamp as state and set the pattern
of the "State Description" metadata to format the timestamp.
label: Last update item
name: update_item
required: false
type: TEXT
groupName: items
- description: Label to be displayed in front of the temperature.
label: Temperature Label
name: tmp_label
required: false
type: TEXT
groupName: labels
- description: Suffix to be displayed after the temperature.
label: Temperature Suffix
name: tmp_suffix
required: false
type: TEXT
groupName: labels
- description: Label to be displayed in front of the humidity.
label: Humidity Label
name: hum_label
required: false
type: TEXT
groupName: labels
- description: Suffix to be displayed after the humidity.
label: Humidity Suffix
name: hum_suffix
required: false
type: TEXT
groupName: labels
- description: Label to be displayed in front of the last update timestamp.
label: Last Update Label
name: update_label
required: false
type: TEXT
groupName: labels
# - default: analyzer
# label: Action default
# name: customAction_action
# required: false
# type: TEXT
# groupName: hidden
# - default: =[props.hum_item, props.tmp_item]
# label: Action default
# name: customAction_actionAnalyzerItems
# required: false
# type: TEXT
# groupName: hidden
parameterGroups:
- name: title
label: Title
- name: items
label: Items
- name: labels
label: Labels
- name: customAction
context: action
label: Action
timestamp: Feb 9, 2025, 10:41:01 AM
component: oh-label-cell
config:
actionPropsParameterGroup: customAction
# action: analyzer
# actionAnalyzerItems: =[props.hum_item, props.tmp_item]
expandable: false
footer: '= (props.update_item ? (props.update_label ? props.update_label :
"") + " " + items[props.update_item].displayState : "")'
# header: = props.title
header: = props.customAction_action
icon: oh:temperature
label: '= (props.tmp_label ? props.tmp_label + " " : "") +
items[props.tmp_item].state + (props.tmp_suffix ? " " + props.tmp_suffix :
"")'
subtitle: '= (props.hum_label ? props.hum_label + " " : "") +
items[props.hum_item].state + (props.hum_suffix ? " " + props.hum_suffix :
"")'
trendItem: = props.tmp_item
There are two things going on here (one I didn’t know until testing your code).
Yes, I was careless when typing up this example and used myWidgetAction as a demonstration. Actually, this trick doesn’t work if your action name base includes the word ‘action’ in it. If you just change everything from customAction to something like customAct (or even ‘asdf’ for that matter), you will fix that issue. Sorry, my bad.
The second issue is a weird one and took me a little time to track down. This doesn’t work if you are trying to do it on the root element of the widget…for…reasons…(I actually have zero explanation for this at this time). If you make the root element of the widget some basic container, such as a simple div and put your label cell inside that, everything works (at least it did in my tests):
component: div
slots:
default:
- component: oh-label-cell
config:
...rest of widget...
Thanks a lot, I’d never have figured that one out!
I went for a slightly different approach for the default values now. Based on an idea from @djal, I used the customAct_action to decide if actionPropsParameterGroup is set. If the action in the properties is undefined, then actionPropsParameterGroup will not be set and therefore it will fall back to the action/actionAnalyzerItems values set before. This requires less code and also seems to work without that basic container.
Here is the code:
uid: TemperatureHumidity
tags:
- humidity
- standalone
- temperature
props:
parameters:
- description: Title of the cell.
label: Title
name: title
required: true
type: TEXT
groupName: title
- context: item
description: The state of this item will be displayed as temperature.
label: Temperature item
name: tmp_item
required: true
type: TEXT
groupName: items
- context: item
description: The state of this item will be displayed as humidity.
label: Humidity item
name: hum_item
required: true
type: TEXT
groupName: items
- context: item
description: The display state of this item will be displayed as last update
timestamp. Use an item with the timestamp as state and set the pattern
of the "State Description" metadata to format the timestamp.
label: Last update item
name: update_item
required: false
type: TEXT
groupName: items
- description: Label to be displayed in front of the temperature.
label: Temperature Label
name: tmp_label
required: false
type: TEXT
groupName: labels
- description: Suffix to be displayed after the temperature.
label: Temperature Suffix
name: tmp_suffix
required: false
type: TEXT
groupName: labels
- description: Label to be displayed in front of the humidity.
label: Humidity Label
name: hum_label
required: false
type: TEXT
groupName: labels
- description: Suffix to be displayed after the humidity.
label: Humidity Suffix
name: hum_suffix
required: false
type: TEXT
groupName: labels
- description: Label to be displayed in front of the last update timestamp.
label: Last Update Label
name: update_label
required: false
type: TEXT
groupName: labels
parameterGroups:
- name: title
label: Title
- name: items
label: Items
- name: labels
label: Labels
- name: customAct
context: action
label: Action
timestamp: Feb 9, 2025, 7:10:06 PM
component: oh-label-cell
config:
actionPropsParameterGroup: '= props.customAct_action ? "customAct" : ""'
action: analyzer
actionAnalyzerItems: =[props.hum_item, props.tmp_item]
expandable: false
footer: '= (props.update_item ? (props.update_label ? props.update_label :
"") + " " + items[props.update_item].displayState : "")'
header: = props.title
icon: oh:temperature
label: '= (props.tmp_label ? props.tmp_label + " " : "") +
items[props.tmp_item].state + (props.tmp_suffix ? " " + props.tmp_suffix :
"")'
subtitle: '= (props.hum_label ? props.hum_label + " " : "") +
items[props.hum_item].state + (props.hum_suffix ? " " + props.hum_suffix :
"")'
trendItem: = props.tmp_item