Repository navigation
List Entries
Some cards take a list of mappings - the cameras of an advanced-camera-card, the entities of an entities card - where the entries differ by a value or two. A nested decluttering card cannot sit inside such a list, because the list is the card's own configuration, not a place for cards. Two steps fill a block of configuration in right there.
On this page:
- A block used more than once:
with: - A block per item:
repeat: - Item templates: a block with defaults of its own
- Limits
with: fills in a block from a variable once, with the values you give it:
decluttering_templates:
cameras:
default:
- camera_entry:
camera_entity: '[[camera_entity]]'
live_provider: go2rtc
card:
type: custom:advanced-camera-card
cameras:
- '[[camera_entry|with:camera_entity=camera.front_door]]'
- '[[camera_entry|with:camera_entity=camera.driveway]]'The pairs after with: are plain text, split on commas. A value can hold a placeholder of its
own (v2.4.0+): [[camera_entry|with:camera_entity=camera.[[room]]]] fills [[room]] in
first. To pass a value that holds a comma, name a mapping variable instead:
[[camera_entry|with:front]], where front is a mapping of the values.
The block's own placeholders are filled in from those values first, then from the card's variables and the dashboard's defaults. A whole-value placeholder keeps its shape, so the same step fills in a mapping or a list entry. Inside a longer string the filled block goes in as JSON text, which is rarely what you want.
The values given to with: win over everything the card has worked out, including the
template's own let:. The block is a fresh fill, so [[row|with:name=Hall]] gives the row
Hall even when the card's template sets let: {name: Lounge}; outside the block,
[[name]] is still Lounge. Each value is the text as written, spaces included, so write
with:name=Hall, not with: name = Hall.
repeat: fills the block in once per item and puts the copies into the list where the
placeholder stands, beside any entries written by hand:
card:
type: entities
entities:
- '[[row|with:entity=sun.sun,name=Sun]]'
- '[[row|repeat:lights]]'
- type: divider
- sensor.kitchen_temperaturevariables:
- row:
entity: '[[entity]]'
name: '[[name]]'
- lights:
domain: light
The copies take the placeholder's place as entries of the list itself, not as a list nested inside it. In a house with two lights, the card above receives:
entities:
- entity: sun.sun
name: Sun
- entity: light.bedroom
name: Bedroom
- entity: light.hallway
name: Hallway
- type: divider
- sensor.kitchen_temperatureThe variable after repeat: is a list, or a source like the ones for_each_from takes,
here every light in the house. What each copy is given depends on what it was made from:
| The item is | The copy gets |
|---|---|
| A mapping | Its keys |
A plain value, such as living_room or 5
|
item, the value |
Text shaped like an entity id, such as light.porch
|
item, and the same text as entity
|
| A copy from a source | What a repeated card's copy gets, total included |
Each copy also knows its place: index, index0, count, first, last. Those exist only
inside repeat:; a single with: fill has no position, so [[index]] there is left
unfilled. A registry source keeps up with the registry, as a repeated card does.
The entity test is on the shape of the text only: lowercase letters and underscores, a dot,
then lowercase letters, digits and underscores. Nothing checks that the entity exists, so
light.porhc still gives entity, and a domain with a digit in it does not count.
A source's filters can hold placeholders. They are filled in from the card's variables before anything is looked up, so one template can list a different room on each card:
decluttering_templates:
room_card:
default:
- row:
entity: '[[entity]]'
- in_room:
area: '[[room]]'
card:
type: entities
title: '[[room]]'
entities:
- '[[row|repeat:in_room]]'type: custom:decluttering-card-plus
template: room_card
variables:
- room: Kitchen
The same goes for any filter: entities: binary_sensor.[[name]]_* finds every binary sensor
whose id starts with the name the card passed.
A repeat: inside another repeat's copy reads that copy's values too, so the outer list can
drive the inner one. Here one card makes a block per room, each listing what is in it:
decluttering_templates:
rooms_stack:
default:
- rooms:
- room: Kitchen
- room: Living Room
- room: Bedroom
- in_room:
area: '[[room]]'
- room_block:
type: entities
title: '[[room]]'
entities:
- '[[row|repeat:in_room]]'
- row:
entity: '[[entity]]'
card:
type: vertical-stack
cards:
- '[[room_block|repeat:rooms]]'
A copy can leave itself out. When the block is an item template whose item: is
gated with if:...?, each copy whose condition does not hold drops out of the list, so
[[camera_entry|repeat:cams]] gives only the cameras that passed. The same goes for a single
fill marked optional: [[camera_entry|with:camera_entity=camera.shed?]] leaves the list when
it comes out empty, rather than putting a blank entry in.
When each copy of a repeat is itself a list, the copies stay lists, so a repeat inside a
repeat gives a list of lists. Write |flat straight after the outer repeat: to lay every
copy out in the one list instead:
decluttering_templates:
detections:
default:
- detect_list:
- detect_type: car
zones: [frontporch_zone, streetparking_zone]
- detect_type: person
zones: [frontporch_zone]
- detect_type: cat
- zone_row: binary_sensor.[[item]]_[[detect_type]]_occupancy
- per_type:
- '[[zone_row|repeat:zones]]'
- binary_sensor.frontporch_[[detect_type]]_occupancy
card:
type: entities
entities: '[[per_type|repeat:detect_list|flat]]'That gives six entities in one list: two zones and the camera for the car, one zone and
the camera for the person, and the camera alone for the cat. Without |flat it would be three
lists, one per type. flat goes one level deep, and a copy that is not a list goes in as it
is.
The cat has no zones:, so [[zone_row|repeat:zones]] gives it nothing. Inside a copy, a
repeat over a list that copy does not have gives no copies, and the
debug report says so. At the card's own level a missing name is still
shown as written and warned about.
When the block wants defaults, or is used on more than one dashboard, write it as a template
whose body is item: instead of card::
decluttering_templates:
camera_entry:
default:
- live_provider: go2rtc
item:
camera_entity: '[[camera_entity]]'
live_provider: '[[live_provider]]'[[camera_entry|with:camera_entity=camera.x]] then reads the template. A name that is both a
template and a variable is the template. What wins, from first to last:
- the item template's own
let: - the values given to
with:, or the copy's values fromrepeat: - everything the card has worked out: its template's
let:, itsvariables:, the view's and dashboard's values, its template's defaults - the item template's
default:
So an item template's let: is fixed for every use, and its default: gives way to anything
passed in.
decluttering_templates:
camera_entry:
let:
- live_provider: go2rtc # every camera, whatever is passed
default:
- title: Camera # unless given one
item:
camera_entity: '[[camera_entity]]'
live_provider: '[[live_provider]]'
title: '[[title]]'[[camera_entry|with:camera_entity=camera.driveway,live_provider=webrtc]] still gives
live_provider: go2rtc, and title: Camera.
A bare [[camera_entry]], with no step, fills the block from the card's values alone,
without the item template's let: or default:. Write [[camera_entry|with:]], with
nothing after the colon, or just [[camera_entry|with]] (v2.5.0+), to have them too.
An item template can extends: another (v2.3.1+), as a card template can: the child starts
from the parent's item:, and a list edit such as __append__ adds to the parent's list:
decluttering_templates:
camera_base:
item:
live_provider: go2rtc
entities: ['[[camera_entity]]', sun.sun]
garden_camera:
extends: camera_base
item:
entities:
__append__: [camera.shed, camera.gate][[garden_camera|with:camera_entity=camera.garden]] then gives live_provider: go2rtc and
entities: [camera.garden, sun.sun, camera.shed, camera.gate].
An item template can say what it repeats over, with the same for_each and
for_each_from a card uses. [[name|repeat]], with nothing after it, then repeats it
over that. for_each can be a list or a placeholder that fills to one, and
for_each_from is filled in from the card's values first, as a
source built from variables is:
decluttering_templates:
light_row:
item:
entity: '[[entity]]'
name: '[[name]]'
listed_rows:
for_each: '[[rows]]'
item:
entity: '[[entity]]'
name: '[[name]]'
every_light:
for_each_from:
domain: light
item:
entity: '[[entity]]'
lights_card:
card:
type: entities
title: '[[title]]'
entities:
- '[[light_row|with]]'
- '[[listed_rows|repeat]]'
- type: divider
- '[[every_light|repeat]]'type: custom:decluttering-card-plus
template: lights_card
variables:
- title: Lights
- entity: light.kitchen
- name: Kitchen
- rows:
- entity: light.hallway
name: Hall
- entity: light.bedroom
name: Bedroom
A bare repeat on a block with neither stays on the card as written.
A variable whose value is a fill, p: '[[probe|with:n=front_door]]', also offers the item
template's own values as they came out for that fill: [[p.found]], or if:p.found. The item
template does the working out and the caller decides what to do with it. Here probe checks
whether a sensor exists, and sensor_row keeps the row only when it does:
decluttering_templates:
probe:
default:
- sensor: binary_sensor.[[n]]
- found: '[[sensor|exists]]'
item:
entity: '[[sensor]]'
sensor_row:
default:
- p: [[probe|with:n=[[n]]]]'
item: '[[p|if:p.found?]]'
sensors_card:
default:
- wanted:
- n: front_door
- n: back_door
- n: garage_door
- n: hallway_motion
card:
type: entities
title: Sensors that exist
entities:
- '[[sensor_row|repeat:wanted]]'
There is no binary_sensor.back_door, so its copy drops out.
Only names something actually asks for are worked out. The template after with: has to be an
item template, one with an item:. The health panel counts p.found as set.
Item templates are not offered in the card editor's template picker, since there is no card to build from one, and the health panel does not call them unused while something reads them.
-
with:pairs are split on commas, then on the first=. Their values are plain text, spaces included. A pair without=is refused. - A list of plain values (numbers, words) gives each copy
item, andentityas well when the value looks like an entity id. See the table above. - Nothing can follow
with:orrepeat:in the chain except|flatafter arepeat:(v2.4.0+):[[row|repeat:lights|upper]]is refused, left as written, and the browser console says so. A?on the end is allowed. -
repeat:over a Jinjatemplate:source is not wired yet. It gives an empty list and says nothing, so the placeholder's place in the list is simply empty. - A block that fills itself in, directly or through other blocks, or nests 6 levels
deep, is refused. So is a card that would need more than 2000 fills in one build: a
repeat:over every entity in a large house, nested inside another, can reach that. - A
repeat:orwith:inside a longer string goes in as JSON text. Stand it alone as the whole value, or as a list entry, to get the structure. -
|stateinside a copy still needs the entity in the card'srebuild_on.
The full list of what each copy gets and what is refused is in Repeat Reference and Placeholder Reference.
Getting started
Core concepts
Content types
Features
- Repeating a Template
- Repeating Sections and Badges
- List Entries
- Sharing Between Dashboards
- Sharing a Template
- Visibility
- Styling
- Visual Editors
- Translations
Reference