Decluttering Card Plus Contents ↓ GitHub ↗

List Entries (v2.3.0+)

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:

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.


A block per item: repeat:

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_temperature
variables:
  - row:
      entity: '[[entity]]'
      name: '[[name]]'
  - lights:
      domain: light

An entities card: the sun from with:, then one row per light from repeat:, then a hand-written divider and sensor

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_temperature

The 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.

Building the source from variables (v2.4.0+)

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

An entities card titled Kitchen listing the kitchen light and the kitchen temperature sensor

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]]'

Three entities cards stacked, one each for the kitchen, living room and bedroom, each listing that room's things

Copies that leave themselves out (v2.3.2+)

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.

One list from a repeat inside a repeat: |flat (v2.4.0+)

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.


Item templates: a block with defaults of its own

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:

  1. the item template’s own let:
  2. the values given to with:, or the copy’s values from repeat:
  3. everything the card has worked out: its template’s let:, its variables:, the view’s and dashboard’s values, its template’s defaults
  4. 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 with its own list: a bare repeat (v2.5.0+)

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

An entities card: Kitchen from the bare with, Hall and Bedroom from the listed rows, then every light

A bare repeat on a block with neither stays on the card as written.

Reading what a fill worked out: [[name.key]] (v2.4.0+)

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]]'

An entities card listing the front door, garage door and hallway motion sensors, with the missing back door left out

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.


Limits

The full list of what each copy gets and what is refused is in Repeat Reference and Placeholder Reference.


Next