You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add dynamic dropdown and selector options from attributes and templates
Let a dropdown or selector generate its options from a list instead of
requiring every option to be hand-written, creating one option per item.
Implements Discussion Nerwyn#137 ("Automatically populate dropdown options from
effects / entity attribute lists"). Builds on the per-option config.option
template variable from Nerwyn#198.
Sources (all backwards compatible with the existing explicit list):
- options_attribute / options_entity: read the list straight from an
entity attribute, e.g. a light's effect_list, with no template. The same
can be written as an `options: { attribute, entity_id }` object.
select/input_select default to their `options` attribute.
- options as a template string: render to a list for computed sources.
Parsed from comma/newline strings or JSON/YAML arrays (including nunjucks
`| dump`, HTML-escaped); items may be {value,label,icon} objects.
- option_template: per-item label/icon/action applied to every generated
option; each item's value is exposed as the `option` variable (alias of
config.option). select/input_select options get a default select_option
action, so those are zero-config.
- Resolved lists are cached on a source signature so long lists stay cheap
on frequent state updates, and re-render when the source changes.
- Selected option label/icon in the dropdown window now render in the
option's own context (also fixes the blank selected label from Nerwyn#198).
- Editor: an "Options source" picker (manual / entity attribute / template)
with a reusable option-template editor.
- Docs: Dropdowns/Selectors, a Dynamic Options section, and worked examples
(Example 9 light effect_list, 10 media_player source_list, 11 climate
hvac_modes selector).
- Tests: parseOptionsList / buildTemplatedOption / resolveOptionsAttribute
(node:test + tsx).
Ref Nerwyn#137
Copy file name to clipboardExpand all lines: README.md
+189-1Lines changed: 189 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -53,6 +53,8 @@ You can override the default behavior of each option by changing their action. T
53
53
54
54
You can also choose to not give any of the dropdown options `Option` values, so that none are ever marked as the selected option. This makes it so that the default dropdown icon and label are always displayed, and the dropdown feature becomes more of a menu for firing different actions rather than one for selecting an option.
55
55
56
+
Instead of writing out every option by hand, you can also generate them from an entity attribute that contains a list (such as a light's `effect_list`) or from a template. This is useful for entities with long, dynamic attribute lists. See [Dynamic Options](#dynamic-options) below and [Example 9](#example-9) for a worked example.
@@ -73,6 +75,8 @@ Like dropdowns, this feature works best with Home Assistant `select/input_select
73
75
74
76
Since each selector option is a custom feature button, you can override its default behavior by changing its tap action. The `Option` field will be the value to compare against the feature's value, whether that is its entity's state or one of its attributes. If they match and are not undefined, then the the option will be highlighted. The option highlight color defaults to the parent card color (usually the tile card color), but can be changed by setting the CSS attribute `--color` to a different value, either for the entire feature or an individual option.
75
77
78
+
Like dropdowns, selectors can also generate their options from an entity attribute list or a template. See [Dynamic Options](#dynamic-options) below and [Example 11](#example-11) for a worked example.
@@ -166,6 +170,80 @@ Like sliders and spinboxes, selectors have a one second delay before updating th
166
170
167
171
Dropdowns can also be assigned their own default icon and label. When no option is selected, the default icon and label are used.
168
172
173
+
#### Dynamic Options
174
+
175
+
Instead of writing out each option by hand, dropdowns and selectors can generate their options from a list, automatically creating one option per item. This is ideal for entities with long, dynamic attribute lists like a light's `effect_list`, a media player's `source_list`, or a `select`/`input_select` entity's `options`. In the configuration UI, set **Options source** to `Entity attribute` or `Template` in the dropdown or selector general options. There are three sources:
176
+
177
+
##### From an entity attribute
178
+
179
+
Point the options straight at an entity attribute that contains a list. This requires no template:
180
+
181
+
```yaml
182
+
- type: dropdown
183
+
entity_id: light.my_light
184
+
value_attribute: effect
185
+
options_attribute: effect_list
186
+
# options_entity: light.other_light # optional, defaults to entity_id
187
+
```
188
+
189
+
The same can also be written as an object on `options`:
A template result can be expressed in any of these forms:
214
+
215
+
- A comma-separated string, which is what the default `{{ state_attr(...) }}` output produces (e.g. `Solid,Rainbow,Fireworks`).
216
+
- A newline-separated string, useful when values themselves contain commas (e.g. `{{ my_list | join('\n') }}`).
217
+
- A JSON or YAML array, which preserves values containing commas and supports objects. Use the `dump` filter to emit JSON, e.g. `{{ my_list | dump }}`. List items may be objects of the form `{ value, label, icon }` (the keys `option`, `id`, `name`, `friendly_name`, and `title` are also accepted as aliases), letting you show a friendly label while selecting a different underlying value:
A template expression must be wrapped in `{{ }}` like all other templates, e.g. `options: "{{ state_attr('light.x', 'effect_list') }}"`. A plain string with no template expression is instead used verbatim as a literal comma-separated list, so `options: "Cool, Warm, Hot"` also works. Attribute sources can use the same object item form as templates.
226
+
227
+
##### Option template
228
+
229
+
For both dynamic sources, an **Option template** is applied to every generated option (with its own label, icon, action, and styles). Each item's value is exposed to the option template's fields as the `option` template variable (also available as `config.option`), so you wire up the label and action once:
230
+
231
+
```yaml
232
+
option_template:
233
+
label: '{{ option }}'
234
+
tap_action:
235
+
action: perform-action
236
+
perform_action: light.turn_on
237
+
target:
238
+
entity_id: light.my_light
239
+
data:
240
+
effect: '{{ option }}'
241
+
```
242
+
243
+
Generated options re-render automatically when their source changes, and the resolved list is cached so that frequent state updates remain cheap even for very long lists.
244
+
245
+
Selected state detection works exactly as it does for manual options: the value of each generated option is compared against the feature's value (its entity's state or attribute). For `select` and `input_select` entities, generated options that have no action of their own are automatically given a `select_option` action, so generating options from these requires no option template at all.
@@ -188,7 +266,7 @@ Buttons, dropdowns, selectors, sliders, and toggles have design variants that ca
188
266
189
267
Almost all fields support nunjucks templating. Nunjucks is a templating engine for JavaScript, which is heavily based on the jinja2 templating engine for Python which Home Assistant uses. While the syntax of nunjucks and jinja2 is almost identical, you may find the [nunjucks documentation](https://mozilla.github.io/nunjucks/templating.html) useful. Most extensions supported by Home Assistant templates are supported by this templating system, but not all and the syntax may vary. Please see the [ha-nunjucks](https://github.com/Nerwyn/ha-nunjucks) repository for a list of available extensions. If you want additional extensions to be added or have templating questions or bugs, please make an issue or discussion on that repository, not this one.
190
268
191
-
You can include the current value of a feature and its units by using the variables `value` and `unit` in a label template. You can also include `hold_secs` in a template if performing a momentary repeat or end action. For toggles you can use the boolean variable `checked` to check whether the toggle is on or off. Each custom feature can also reference its entry using `config` within templates. `config.entity` and `config.attribute` will return the features entity ID and attribute with their templates rendered (if they have them), and other templated config fields can be rendered within templates by wrapping them in the function `render` within a template. Information about the parent card such as its entity ID, state, and attributes can be accessed using `stateObj`. The structure of `stateObj` can be found [here](https://github.com/home-assistant/home-assistant-js-websocket/blob/1d51737f6092b95e2bc98e85aca752771b97b760/lib/types.ts#L72-L96) as a `HassEntity` type and is listed below.
269
+
You can include the current value of a feature and its units by using the variables `value` and `unit` in a label template. You can also include `hold_secs` in a template if performing a momentary repeat or end action. For toggles you can use the boolean variable `checked` to check whether the toggle is on or off. For dropdown and selector options you can use the variable `option` (also available as `config.option`) to reference that option's own value, which is especially useful with [dynamic options](#dynamic-options). Each custom feature can also reference its entry using `config` within templates. `config.entity` and `config.attribute` will return the features entity ID and attribute with their templates rendered (if they have them), and other templated config fields can be rendered within templates by wrapping them in the function `render` within a template. Information about the parent card such as its entity ID, state, and attributes can be accessed using `stateObj`. The structure of `stateObj` matches the [Home Assistant websocket `HassEntity` type definition](https://github.com/home-assistant/home-assistant-js-websocket/blob/1d51737f6092b95e2bc98e85aca752771b97b760/lib/types.ts#L72-L96) and is listed below.
192
270
193
271
<details>
194
272
@@ -2457,3 +2535,113 @@ transparent: true
2457
2535
```
2458
2536
2459
2537
</details>
2538
+
2539
+
## Example 9
2540
+
2541
+
Generating dropdown options dynamically from a light's `effect_list` attribute. The dropdown lists every effect the light supports, marks the active one as selected, and tapping an option sets that effect — all without hand writing a single option. If the light's firmware adds or removes effects, the dropdown updates automatically.
The same pattern works for any entity with a list attribute, for example a media player's `source_list` (paired with `media_player.select_source`) or a climate entity's `preset_modes`. For `select` and `input_select` entities you can omit both `options_attribute` and `option_template`, since the `options` attribute is used and a `select_option` action is generated for you:
2573
+
2574
+
```yaml
2575
+
- type: dropdown
2576
+
entity_id: input_select.scene
2577
+
options_attribute:
2578
+
```
2579
+
2580
+
If you need a computed list instead of a single attribute, point `options` at a template that renders to a list, for example to merge two lists or filter them:
2581
+
2582
+
```yaml
2583
+
options: "{{ (state_attr(config.entity, 'effect_list') or []) | reject('eq', 'Solid') | list }}"
2584
+
```
2585
+
2586
+
## Example 10
2587
+
2588
+
Generating a dropdown from a media player's `source_list`, with the active source marked as selected and tapping a source switching to it. A dropdown is a good fit here because source lists can be long.
Generating a **selector** from a climate entity's `hvac_modes`. Because a selector lays its options out in a single row, attribute lists with only a handful of items (like HVAC modes, fan presets, or vacuum fan speeds) work best; use a dropdown for longer lists. The climate state is the active HVAC mode, so the matching option is highlighted automatically.
0 commit comments