I totally agree that they are under-documented and confusing, partly because they are very open-ended. I have a suspicion that they may be of little practical value to most users.
The basic function of state-based Template selects seems to be to make it so you do not have to create separate input select helpers and automations. If you want a single functional unit, they can be used like mini-automations with State triggers.
Semi-Practical Examples
Example 1: Proxy/Translate an Existing Select or Input Select entity
Integration-created Select entities may use options that are not labelled in a way that you like or that is easily understood. Or you may live in a bilingual household, and want to have a version in each language, but keep their states entrained.
template:
- select:
- name: "Color Picker Translated"
unique_id: color_selector_translated
state: >
{% set opt = states('select.color_selector') %}
{% set mapper = {
'Rojo': 'Red',
'Azul': 'Blue',
'Verde': 'Green',
'Amarillo': 'Yellow',
'Blanco': 'White'
}%}
{{ mapper.get(opt) }}
options: "{{['Red','Blue','Green','Yellow','White']}}"
select_option:
- service: select.select_option
data:
option: >
{% set mapper = {
'Red': 'Rojo',
'Blue': 'Azul',
'Green': 'Verde',
'Yellow': 'Amarillo',
'White': 'Blanco'
}%}
{{ mapper.get(option) }}
target:
entity_id: select.color_selector
availability: "{{ state_attr('select.color_selector', 'options') is defined }}"
Example 2: Template Selects in place of an automation
I use this template select to switch sources on an old stereo receiver. The select_option
sequence below saves the selected value to an input text helper and passes it along to a script that handles sending IR commands to the stereo receiver.
template:
- select:
- name: "RCA Stereo Source"
unique_id: rca_stereo_source_select
state: "{{ states('input_text.rca_receiver_output') }}"
options: "{{['Cable','CD','AUX','AM/FM','DVD']}}"
select_option:
- service: input_text.set_value
target:
entity_id: input_text.rca_receiver_output
data:
value: "{{ option }}"
- service: script.rca_receiver_send_command
data:
command: "{{ option }}"
repeats: 2
availability: "{{ states('input_text.rca_receiver_output') is defined }}"
Example 3: Dynamic, Area-based Scene Selector
The following auto-populates a selector for all the scenes assigned to a given Area. The state and options are presented in the form of friendly names for UI usability. As above, the select_option
sequence saves the selected value to an input text helper. Then the selected scene is turned on.
template:
- select:
- name: "Basement Scenes"
state: "{{ states('input_text.selected_basement_scene') }}"
options: >
{{expand(area_entities("Basement"))
| selectattr('domain', 'eq', 'scene')
| map(attribute='name') | list }}
select_option:
- variables:
entity: >
{{ states.scene | selectattr('name', 'eq', option)
|map(attribute='entity_id')|join }}
- service: input_text.set_value
target:
entity_id: input_text.selected_basement_scene
data:
value: "{{ option }}"
- service: scene.turn_on
target:
entity_id: "{{ entity }}"
Example 4: Partially Entrained Booleans
The following auto-populates a selector with all Input booleans entities that match a specific naming scheme. The state and options are presented in the form of entity IDs. The select_option
sequence turns the selected entity ‘on’. Then the non-selected booleans are turned ‘off’.
template:
- select:
- name: "Partially Entrained Booleans"
state: >-
{{ (expand(this.attributes.options
| select('is_state', 'on')
| list) | sort(attribute='last_changed', reverse=1)
| map(attribute='entity_id')|list)[0] or
(expand(this.attributes.options) | sort(attribute='last_changed', reverse=1)
| map(attribute='entity_id')|list)[0]}}
select_option:
- service: input_boolean.turn_on
target:
entity_id: "{{ option }}"
- variables:
boolean: |
{{ this.attributes.options |reject('eq', option)|list}}
- service: input_boolean.turn_off
target:
entity_id: '{{ boolean }}'
options: >
{{ states.input_boolean
| selectattr('object_id', 'match', 'test_bool_')
| map(attribute='entity_id')
| list }}
Template selects are not read-only… they are like Input select helpers, but the options:
can be either static lists (like an Input select) or a list derived from a template.
Example 5: Merged Options Example
Maybe you already had two Input select helpers that are fully automated, but you want to combine them so there’s only one selector on your dashboard:
template:
- select:
- name: "Merged Audio Selects"
state: >
{{expand('input_select.radio_stations','input_select.music_genres')
| sort(attribute='last_changed', reverse=true)
| map(attribute='state')
| list | first}}
options: >
{{ state_attr('input_select.music_genres', 'options')
+ state_attr('input_select.radio_stations', 'options') }}
select_option:
- service: input_select.select_option
target:
entity_id:
- input_select.music_genres
- input_select.radio_stations
data:
option: "{{ option }}"
The state:
template defines their current value. As far as I can tell, it has to render as one of the items in the options:
list or it will return “unavailable”.
select_option:
is the analog to the Action section of an automation. It defines what to do when there is a new selection event.
That sounds like a job for a template sensor or a set of time of day sensors…
Mapper-based time of day sensor
template:
- sensor:
- name: Time of Day
state: >
{% set a = today_at("05:00")%}
{% set b = today_at("07:00")%}
{% set c = today_at("12:00")%}
{% set d = today_at("18:00") %}
{% set e = today_at("20:00")%}
{% set f = today_at("01:00")%}
{% set map = {
a < now() <= b: 'Early Morning',
b < now() <= c: 'Morning',
c < now() <= d : 'Afternoon',
d < now() <= e: 'Evening',
e < now() < f + timedelta(days=1): 'Night',
today_at() < now() <= f: 'Night',
f < now() <= a: 'Late Night'
} %}
{{ map.get(True) }}