thomasloven / lovelace-card-mod

🔹 Add CSS styles to (almost) any lovelace card
MIT License
1.12k stars 167 forks source link

'if config.entity is none' template doesn't work #134

Closed Mariusthvdb closed 8 months ago

Mariusthvdb commented 3 years ago

My Home Assistant version: 2021.6.6

My lovelace configuration method (GUI or yaml): YAML What I am doing:

trying to have a conditional badge, templating on existence of the config.entity

  - entity: sensor.state_badge
    card_mod:
      style: |
        :host {
          display: {% if config.entity is none %}none{%endif%}
        }

Also tried{% if not config.entity %} and {% if config.entity not is defined %}

What I expected to happen:

don't display the badge if the entity doesn't exist (yet)

What happened instead:

Schermafbeelding 2021-06-29 om 10 00 31

Minimal steps to reproduce:

# The least amount of code possible to reproduce my error
  - entity: sensor.state_badge
    card_mod:
      style: |
        :host {
          display: {% if config.entity is none %}none{%endif%}
        }

# End of code

Error messages from the browser console:

Unhandled Promise Rejection: TypeError: null is not an object (evaluating 'this.shadowRoot.querySelector')

though the above error also shows on correct badges, and I have reported that in another issue

please also see a community post.

as an example:

    card_mod:
      style: |
        :host {
          display: {% if states('binary_sensor.updater') == 'off' %} none {% endif %}
        }

works perfectly.

By putting an X in the boxes ([]) below, I indicate that I:

thomasloven commented 3 years ago

{% if config.entity is undefined %}none{%endif%}

{% if config.entity is not defined %}none{%endif%}

Mariusthvdb commented 3 years ago

thanks, but, really sorry, and I did also try that, and it just doesn't work, resulting in a top level badge still being displayed (never mind the formatting)

Schermafbeelding 2021-06-30 om 08 19 33

this however does work:

{% if states(config.entity) == 'unknown' %} display: none {% endif %}

Note I changed the syntax of the condition to be:

    card_mod:
      style:
        <<: &exist
          .: |
           :host {
             {% if states(config.entity) == 'unknown' %} display: none {% endif %}
           }

and of course I also did when testing the other templates. so unlike anywhere else in Jinja templates, with this card_mod, we somehow can not check for the states entity, but can only do so with the states state.

adulovic commented 3 years ago

Seems related, so I won't open a new issue...

Since I switched to using card-mod in themes, my error log gets filled with hundreds of ERROR (MainThread) [homeassistant.helpers.template] Template variable error: 'dict object' has no attribute 'entity' when rendering

Seems that this error is generated for every row without an entity and I apparently have many such rows. Two examples that immediately come to mind: - type: divider and - type: custom:template-entity-row

A quick fix is to wrap {% if states(config.entity) %}...{% endif %} around the template css code. You might want to update your examples to include those two additional lines.

adulovic commented 3 years ago

A simple solution to the OP's issue could be to set display: none; as a default, then use if states(config.entity) to change it to display: block; or whatever else he needs.

Mariusthvdb commented 3 years ago

Id rather use

{% if states(config.entity) == 'unknown' %} display: none {% endif %}

which does work, but is avoiding the issue at hand (simply by the states() that always returns 'unknown' on non existing entity states). In this case that is the true issue, and I believe Thomas re-openend because of that.

About your issue, I fear it is another matter after all, simply because you get a template error (and in my case there is no error like that/at all (dont think the error I posted is related). You should probably check (and guard) your templates. Divider doesn't throw an error.

Mariusthvdb commented 2 years ago

no happening in my config anymore, should we close?

Zerwin commented 2 years ago

I had it still happen for me, but my solution was just to follow what was done here by ildar, even though I wasn't using rows but cards. https://github.com/thomasloven/lovelace-card-mod/issues/180#issuecomment-1106890949

I noticed it even happened when I was using a blank dashboard and then tried adding a card. Maybe the template tries to apply also to cards in the editor ? Which would of course not have any config.entity

ildar170975 commented 2 years ago

Maybe the template tries to apply also to cards in the editor

Do not think so. I observed this error even for dashboards in yaml mode (i.e. not available to be edited in UI). Also, I do not remember exactly whether these errors occurred on HA startup or after.

to cards in the editor ? Which would of course not have any config.entity

Why? IMHO the "config.entity" variable works in a card opened in Editor too.

Zerwin commented 2 years ago

For me they occurred every time I opened the edit dashboard menu, and sometimes even just by opening a dashboard with cards in it.

Why? IMHO the "config.entity" variable works in a card opened in Editor too.

I didn't mean a card that is opened in the editor, but pressing the edit dashboard -> Add card button, and then the list of cards that pop up, sorry if that was unclear. Some of these cards seemed to have triggered it for me, and I don't think these cards, which aren't even added to the dashboard yet, have any type of entity.

skynet01 commented 1 year ago

I tried wrapping config.entity... in states(config.entity...) and it's not working for me. Anyone know why I am getting this error? The code works fine and my fans rotate properly would be great to fix the error below.

Error: Template variable error: 'dict object' has no attribute 'entity' when rendering '@keyframe spin...

Theme file:

  card-mod-row-yaml: |
    "*:first-child$": |
      @keyframes spin {
        0% {
          transform: rotate(0deg);
        }
        100% {
          transform: rotate(359deg);
        }
      }
      state-badge {
            {% if config.entity.startswith('fan.') and is_state(config.entity, 'on') and state_attr(config.entity, 'percentage') | int <= 15 %}
                animation: spin 4s infinite linear;
            {%- elif config.entity.startswith('fan.') and is_state(config.entity, 'on') and state_attr(config.entity, 'percentage') | int <= 33 %}
                animation: spin 3s infinite linear;    
            {%- elif config.entity.startswith('fan.') and is_state(config.entity, 'on') and state_attr(config.entity, 'percentage') | int <= 67 %}
                animation: spin 1.5s infinite linear;
            {%- elif config.entity.startswith('fan.') and is_state(config.entity, 'on') and state_attr(config.entity, 'percentage') | int <= 100 %}
                animation: spin 0.75s infinite linear;    
            {%- else -%}
                animation-duration: 0s;
            {%- endif %}
      }
Mariusthvdb commented 1 year ago

this would be more for the community probably, since you're having a templating question, but anyways, you'd be better off simplifying like:

            {% set fan = 'fan.luchtreiniger_woonkamer' %}
            {% set test = fan.startswith('fan.') and is_state(fan, 'on') %}
            {% if test %}
              {% set perc = state_attr(fan, 'percentage')|int %}
              {% if perc <= 15 %} animation: spin 4s infinite linear;
              {%- elif perc <= 33 %} animation: spin 3s infinite linear;    
              {%- elif perc <= 67 %} animation: spin 1.5s infinite linear;
              {%- else  %} animation: spin 0.75s infinite linear;    
              {% endif %}
            {%- else -%} animation: none;
            {%- endif %}

(ofc replace the verbose entity I used for testing with config.entity) and then check the error. You didnt completely post the logged error, so that would help too

btw, I just tested the simplified:

            state-badge {
              {% if is_state(config.entity,'on') %}
                animation: rotation 2s linear infinite, colorize 5s linear forwards 1;
              {% endif %}
            }

on a direct fan entity in an entities card, and its working fine.

as does :

      card_mod:
        style:
          div#wrapper: |
            state-badge {
              animation: {% if is_state(config.entity,'on') %}
                         {% set perc = state_attr(config.entity,'percentage')|int %}
                         {% if perc <= 15 %} rotation 4s infinite linear, colorize 5s linear forwards 1;
                         {%- elif perc <= 33 %} rotation 3s infinite linear, colorize 5s linear forwards 1;
                         {%- elif perc <= 67 %} rotation 1.5s infinite linear, colorize 5s linear forwards 1;
                         {%- else  %} rotation 0.75s infinite linear, colorize 5s linear forwards 1;
                         {% endif %}
              {% else %} none;
              {% endif %}
            }
            @keyframes rotation {
              0% {
                transform: rotate(0deg);
              }
              100% {
                transform: rotate(360deg);
              }
            }
            @keyframes colorize {
              0% {
                background: steelblue;
              }
              100% {
                background: lightseagreen;
              }
            }
ildar170975 commented 1 year ago

@skynet01

I tested exactly same code you posted, just added color:

cm_test_test:

  card-mod-theme: cm_test_test

  card-mod-row-yaml: |
    "*:first-child$": |
      @keyframes spin {
        0% {
          transform: rotate(0deg);
        }
        100% {
          transform: rotate(359deg);
        }
      }
      state-badge {
            {% if config.entity.startswith('fan.') and is_state(config.entity, 'on') and state_attr(config.entity, 'percentage') | int <= 15 %}
                animation: spin 4s infinite linear;
                color: cyan;
            {%- elif config.entity.startswith('fan.') and is_state(config.entity, 'on') and state_attr(config.entity, 'percentage') | int <= 33 %}
                animation: spin 3s infinite linear;    
                color: lightgreen;
            {%- elif config.entity.startswith('fan.') and is_state(config.entity, 'on') and state_attr(config.entity, 'percentage') | int <= 67 %}
                animation: spin 1.5s infinite linear;
                color: orange;
            {%- elif config.entity.startswith('fan.') and is_state(config.entity, 'on') and state_attr(config.entity, 'percentage') | int <= 100 %}
                animation: spin 0.75s infinite linear;    
                color: red;
            {%- else -%}
                animation-duration: 0s;
            {%- endif %}
      }

Test card:

type: entities
entities:
  - entity: input_number.test_level_1
    name: speed
  - type: section
  - entity: fan.virtual_fan_kitchen_test
  - type: attribute
    entity: fan.virtual_fan_kitchen_test
    attribute: percentage
  - type: custom:hui-element
    card_type: markdown
    content: |
      <=15 - cyan
      <=33 - lightgreen
      <=67 - orange
      <=100 - red

Test automation:

mode: single
trigger:
  - platform: state
    entity_id:
      - input_number.test_level_1
action:
  - service: fan.set_percentage
    data:
      percentage: >-
        {{ states('input_number.test_level_1') | int }}
    target:
      entity_id: fan.virtual_fan_kitchen_test

It works fine, no errors in Code Inspector: cm1 HA 2023.2.5, Chrome, Win10

skynet01 commented 1 year ago

Ok I figured out what the issue was. I had quotes around the name of the theme card-mod-theme: "my_theme" I noticed that your code above didn't have them. So removing the quotes fixed it. Thank you guys! And thank you @Mariusthvdb for a simplified cleaner code!

my_theme:

  card-mod-theme: my_theme

  card-mod-row-yaml: |
        "*:first-child$": |
            state-badge {
                  animation: {% if is_state(config.entity,'on') %}
                             {% set perc = state_attr(config.entity,'percentage')|int %}
                             {% if perc <= 15 %} rotation 4s infinite linear, colorize 5s linear forwards 1;
                             {%- elif perc <= 33 %} rotation 3s infinite linear, colorize 5s linear forwards 1;
                             {%- elif perc <= 67 %} rotation 1.5s infinite linear, colorize 5s linear forwards 1;
                             {%- else  %} rotation 0.75s infinite linear, colorize 5s linear forwards 1;
                             {% endif %}
                  {% else %} none;
                  {% endif %}
                }
                @keyframes rotation {
                  0% {
                    transform: rotate(0deg);
                  }
                  100% {
                    transform: rotate(360deg);
                  }
                }
skynet01 commented 1 year ago

I saw that as well, I made modifications but I was still getting an error. So now both issues are fixed with Marius' help.

Mariusthvdb commented 1 year ago

this is even more fun:

              animation: {% if is_state(config.entity,'on') %}
                         {% set perc = state_attr(config.entity,'percentage')|int %}
                         {% set base = 'rotation infinite linear, colorize 5s linear forwards 1' %}
                         {% if perc <= 15 %} 4s {{base}};
                         {%- elif perc <= 33 %} 3s {{base}};
                         {%- elif perc <= 67 %} 1.5s {{ base}};
                         {%- else  %} 0.75s {{base}};
                         {% endif %}
                         {% else %} none;
                         {% endif %}
skynet01 commented 1 year ago

Bonus: have the spinning slow down / speed up to the speed set instead of just switching between states 😂

skynet01 commented 1 year ago

After the latest update the error seem to have came back again. Any ideas?

2023-03-06 12:29:41.794 ERROR (MainThread) [homeassistant.helpers.template] Template variable error: 'dict object' has no attribute 'entity' when rendering 'state-badge {
      animation: {% if is_state(config.entity,'on') %}
                 {% set perc = state_attr(config.entity,'percentage')|int %}
                 {% if perc <= 15 %} rotation 4s infinite linear, colorize 5s linear forwards 1;
                 {%- elif perc <= 33 %} rotation 3s infinite linear, colorize 5s linear forwards 1;
                 {%- elif perc <= 67 %} rotation 1.5s infinite linear, colorize 5s linear forwards 1;
                 {%- else  %} rotation 0.75s infinite linear, colorize 5s linear forwards 1;
                 {% endif %}
      {% else %} none;
      {% endif %}
    }
    @keyframes rotation {
      0% {
        transform: rotate(0deg);
      }
      100% {
        transform: rotate(360deg);
      }
    }'
ildar170975 commented 1 year ago

Your style was applied to a card which does not have "config.entity" variable defined.

skynet01 commented 1 year ago

anyway to update the above to fix it. I apply it to the whole template and not a specific card so it might be possible what you are saying is true

ildar170975 commented 1 year ago

https://github.com/thomasloven/lovelace-card-mod/issues/257#issuecomment-1446227419

skynet01 commented 1 year ago

Thank you, surrounding it with if statement fixed it. Don't know why I didn't think of that. Thank you so much for your help!

thomasloven commented 8 months ago

Could someone update me on the status of this one?

Looking at it now, the code in the first post is missing a ;.

Mariusthvdb commented 8 months ago

As said earlier : not seeing this anymore

I’ll recheck if the failing ; was the culprit….