Lovelace: Button card

Ok, I have a thought on this. I’m wondering if it has something to do with when certain javascript templates are evaluated. I’m guessing that what happens when using these config templates is something like this:

  • Upon loading of the lovelace card (button-card), the config template is read into memory.
  • variables are merged
  • states are merged
  • ??? javascript templates within the config template are evaluated and the results substituted
  • card is rendered

I’m wondering about the 4th step above. Let’s look at an example, shall we? :slight_smile:

If in my config template like activity_button, I have the following code in the tap_action block:

    tap_action:
      action: >
        [[[
          return (entity.attributes.current_activity === variables.var_activity ? 'none' : 'call-service' );
        ]]]
      service: remote.turn_on
      service_data:
        entity_id: '[[[ return entity.entity_id; ]]]'
        activity: '[[[ return variables.var_activity; ]]]'

I’ve been assuming that those javascript templates get carried over as-is to the final version of the card source so they remain dynamic. But now I’m wondering if those actually get evaluated and substituted so that after loading the template, what’s left is:

    tap_action:
      action: none
      service: remote.turn_on
      service_data:
        entity_id: 'remote.harmony_hub'
        activity: 'Watch TV'

So, if “Watch TV” was the current activity when I reloaded the page, I can click on another activity button and the service for that button gets called but my Watch TV button stays blue since the color was hard coded by the already evaluated javascript code. Trying to go back to “Watch TV” would result in nothing happening because as we can see the service action is set to “none” and doesn’t change dynamically anymore.

So, if I’m correct, that would mean any javascript templating that I need to remain dynamic needs to be in the actual card config and not the config template. Does any of that sound reasonable?

How can I define the color of both the icon and the button? It seems it’s either one or the other. The first post in this thread shows a gray button with pink icon, so it looks possible, but I just can’t seen to get there. I need a gray button with a red icon.

it’s done in styles. gray button means background of your card. red is color of your icon.
does it make sense?

where’s your code?

The templates are evaluated on each render of the card (that is every time the hass object is modified when you have a template in your card or when the config is modified).
javascript templates are never replaced with their resulting value, whether they comme from card templates or not. It is evaluated when it needs to be used.
I’ve found a bug though in the card by checking how this could happen, but it’s not affecting what you experience.

I’m going to have a look if I can reproduce your issue (I also have an harmony hub, and am also using button-card templates and javascript templates inside the button template and never have had an issue with that)

Well, I moved the conditional javascript that should result in either call-service or none depending on the current activity to the card config and it now works. I also moved the conditional icon color code to the state area and that works as well. I had earlier created a couple sensors that have the current activity on my hubs as the state to make things a little easier.

Before in config template:

    tap_action:
      action: >-
         [[[
           return(entity.state === variables.var_activity ? 'none' : 'call-service');
         ]]]
      service: remote.turn_on
      service_data:
        entity_id: '[[[ return variables.var_hubentity; ]]]'
        activity: '[[[ return variables.var_activity; ]]]'

After, putting the conditional into the card config:

              tap_action:
                action: >-
                  [[[
                    return(states['sensor.harmony_up_activity'].state === 'Watch TV' ? 'none' : 'call-service');
                  ]]]

It was really acting like the first js in the config template was being evaluated and substituted as 'none' so that I could not ever get it to switch to that activity again even after switching away. The only bummer is I have to hard code some values in that conditional in the card config because it appears the 'entity' object and the 'variables' object are not available from within the card config. Is that supposed to be that way? I’m declaring 'entity: <entity_name>' in both the config template and the card config. Those two objects are available when in js code within the config template. In the card config, I only have 'hass' and 'states' available.

All the other js templates I have in the config template would cause no harm if they were evaluated and replaced since those values never change in the life of the card.

I could probably come up with a stripped down version of my stuff that would exhibit the problem if you want to have a look.

Right, the bug I’ve found in the card was related to *_action and the templates associated with it to see if you can click the button or not. So the fix I have put in place should correct that issue.

But I thought that the color was not changing either?

I don’t understand?

There’s no need to declare it twice. The config is fully merged between templates and the instance’s config of the button-card before anything happens.

I don’t understand that either?

Thanks for the new features @RomRider, especially the recent ability to display an alternative state.

I’m trying to change the output of an input_datetime that just has the time enabled. The state displays something like 07:30:00 but I’m wanting it to display 07:30 instead.

I think I’m mixing up my template syntax but I’m not sure how it can be put right.

Taking the following example from an automation:

    trigger:
      - platform: template
        value_template: "{{ states('sensor.time') == (state_attr('input_datetime.wakeup_alarm', 'timestamp') | int | timestamp_custom('%H:%M', True)) }}"

I would like to use timestamp_custom to convert the timestamp attribute within the button card.
This shows the timestamp:

state_display: >
  [[[ return entity.attributes.timestamp ]]]

but is it possible to convert the timestamp output (eg 27000) to 07:30 using timestamp_custom?

I’ve tried various combinations to integrate the two but my lack of template knowledge isn’t helping. I’ve also looked at other template examples in this thread for inspiration, but no luck so far.

I’d do it this way:

state_display: >
  [[[
    const ar = entity.state.split(':')
    return `${ar[0]}:${ar[1]}`
  ]]]

dude, you’re spending way to much time trying to make this work only in the front end. Make template switches for each activity. You won’t need to have any of this templating here. And, you’ll be able to use the template switches with any other medium; alexa, google home, other hubs, etc.

The color is working as I was able to template it without requiring conditional code like what the 'tap_action' was doing. I set the default color in a 'styles' block, then in the 'state' block, I have this:

    state:
      - value: '[[[ return variables.var_activity; ]]]'
        styles:
          icon:
            - color: 'rgb(59,66,249)'

That’s in the config template. IF that was getting evaluated and substituted when the card is loaded, it wouldn’t make any difference because the activity never changes for that button. Before, I was using a conditional that was comparing the current activity to the button activity and that was acting the same as the 'tap_action' where it appeared it was being evaluated and substituted as whatever was the current activity at card load time, so the color never changed when switching to another activity.

Now, what I mean about the js objects. If in the config template, I have a js template like this:

[[[ console.log(entity); return(blah, blah, blah); ]]]

In the console, I see the dump for entity object as you would expect. If I have the same js template, but it’s located in the card config instead, the console logs “undefined” and trying to use something like 'entity.attributes' throws an exception like “cannot access attributes on undefined object”. The same goes for the 'variables' object. Works in the config template, but undefined in the card config.

I know that sounds completely crazy since theoretically once the config template has been merged with the card config you would think there could be no differences anymore. That’s why it’s a head scratcher for me. :slight_smile:

oh cool, yes that makes sense, thank you! Half the fun is knowing what is possible, especially to a non-coder like me. :slight_smile:

You always have to check for undefined in your templates if you’re doing goofy stuff. I start all my button templates with

if (entity === undefined)
  return '&nbsp;';

Haha, I know, right?

The thing is I’m trying to make a full remote control in lovelace. The activity buttons are just one small part of it. The other buttons should be fairly straight forward as they don’t require any complex conditonal features. This is my first foray into the button-card. It’s a great thing but it’s also quite complex with a lot of stuff and I’m trying to learn and understand it.

I’m a developer. It’s in my nature to try and understand when things don’t work the way I think they should to see if it’s just my lack of understanding how something is supposed to work (usually the case), or if it’s something I can help contribute to and help improve a project or documentation.

But I hear 'ya :stuck_out_tongue_closed_eyes:

I have exactly what you’re after. I’m telling you how to get it done :wink:

That is evaluated, so I don’t see a problem but it’s wrong, because your remote state is on, not the activity name. If you want to do it the proper way:

    state:
      - value: '[[[ return variables.var_activity === entity.attributes.current_activity; ]]]'
        operator: template
        styles:
          icon:
            - color: 'rgb(59,66,249)'

That might happen when the hass object is not yet assigned to the card (which happens asynchronously) when the card tries to render the first time. I’ll update the code so that it doesn’t render if there is no hass object (actually is cleaner but not required :slight_smile: )

BTW I think I’ve understood what is overall wrong with what you do: You expect entity.state to be equal to the activity, but it is not! It is on or off.
This will correct the issue:

    tap_action:
      action: >-
         [[[
           return entity && entity.attributes && entity.attributes.current_activity === variables.var_activity ? 'none' : 'call-service';
         ]]]

And +1 to what @petro is saying. I’m also using switches templates for that:
image

3 Likes

question

how can i we define somekind of static text for a title/name

example

- name: "[[[return ${states[‘sensor.version’].state}]]]"

but i want to display this: , the words “update available:” before it

- name: "Update available: [[[return ${states[‘sensor.version’].state}]]]"

thnx in advance!

- name: "[[[return `Update available: ${states['sensor.version'].state}`]]]"
1 Like

Does the lock function disable the button? I have an automation that changes an input_boolean to on. The user is allowed to turn it off but not on. I’m trying to use the lock feature but I don’t think I understand this feature correctly. Looking for a way to disable the button when status is off. Thanks

hide the button instead of locking it. Locking is to make sure you don’t miss click. Use a conditional card.

1 Like

yep, that’s what I was thinking I would need to do…thanks for your quick response