Lovelace-auto-entities: How to provide option for template filter

Hi,

I’m parsing sensor attribute which contains a list of entityIds and trying to render them as Button cards inside grid using lovelace-auto-entities.

The sensor attribute looks like

light.yoga_room_lights, light.rohit_office_lights

and I’m able to render this value as entity cards using below

type: custom:auto-entities
card:
  type: entities
  title: Monitored Devices
filter:
  template: |
    {{ state_attr('sensor.monitored_entities','entities') }}
sort:
  method: last_changed
  ignore_case: true
  numeric: false

but as soon as I change type to grid and change it as per the doc as below, it does not render

type: custom:auto-entities
card:
  type: grid
  title: Monitored Devices
card_param: cards
filter:
  template: |
    {{ state_attr('sensor.monitored_entities','entities') }}
sort:
  method: last_changed
  ignore_case: true
  numeric: false

based on the doc it needs following:

options:
        type: button

but also as per the doc, the option field is only available to include and exclude filters and I’m using template filter here.

Please advise how to handle this.

1 Like

Hi, this thread is a bit older, but I found it when I ran into the same issue and wanted to document my solution, maybe it is still relevant for @rlchandani.

After a bit of fiddling, I came up with a hack, formed by the following train of thoughts:

  • We can’t pass anything via options if we want to use template
  • The value of template (after evaluation of the template) is a list of entity_ids that is passed to cards, e.g. ['light.foo','light.bar']
  • To include the type:button, we would have to pass [{'entity':'light.foo','type':'button'},{'entity':'light.bar','type':'button}], so not a list of strings, but a list of key:value maps (dicts in python).
  • Which is not good, because we can’t (as far as I know) dynamically construct lists and dicts inside jinja templates and this is also where filter pipelines come to their limits.
  • But wait :bulb:, we don’t really pass a list, we pass a string that can be parsed as a list!
  • So we don’t have to generate a list of dicts, we have to generate a string that looks like it:

So:

filter:
  template: >
    [
    {% for e in ['light.foo','light.bar'] %}
      {{ {'entity': e, 'type': 'button' } }} 
      , 
    {% endfor %} 
    ]

evaluates to

[
  {'entity': 'light.foo', 'type': 'button'} 
  , 
  {'entity': 'light.bar', 'type': 'button'} 
  , 
]

Which works good enough as a list of key:value maps for the entities in grid and we can have our type:button for each entity:light :white_check_mark:

The whole thing can now be tuned to get the list of entities from an attribute as above, use dict(k=v) for readabilty, look up more states on the way and also do everything in a single line:

filter:
  template: >
    [ {% for e in state_attr('sensor.monitored_entities','entities') %} {{ dict(entity=e, type='button', name=state_attr(e,'my_custom_name' ) }} , {% endfor %} ]

Now it reads (almost) like a list comprehension :yum:

(But remember, it does not actually create a list, just a string that looks like one, so we can’t append any filters for iterables (e.g. | select(...))

(( Which might be doable though, with a crazy construct of map, to_json(), format, and from_json :thinking: ))

3 Likes

I’ve been pulling my hair out for the past 8 hours trying to do this - your solution saved the day! What an elegant solution :smile: