Lovelace: Button card

Yes it’s possible. But what is your question? As a side note, you can do that using a script in homeassistant and call that script from the button-card so no need for templates.

You can access window.location in the JS templates which contains the URL of the current page.

You can already template any property including action in all the *_action fields.

Use vh or vw as units but percent should work too (if not using aspect_ratio)

Don’t use absolute positioning, use the grid to achieve what you want to do. See here

So my idea was to change an action depending on the state for my alarm button. However upon further investigation I’ve gone with conditionals buttons instead.

Thanks.

Ha, I didn’t know that, thanks!
this is the verbose url of course, while I would love to use the view, to make things simpler and easier to read in the templates. Like we can do in Custom header as described on Custom Header
would it be an accepted FR to support some of these builtin variables on Button-card too?

ok thanks, will give it a go. should I use templates on each property individually, like below, or is there a smart way of doing so in short-hand:

hold_action:
  action: >
    [[[ if (window.loaction == 'path.to.home') return 'navigate';
        return 'call-service' ;]]]
  navigation_path: >
    [[[ if (window.loaction == 'path.to.home') return 'developer';
        return none ;]]]
  service: >
    [[[ if (window.loaction == 'path.to.home') return none;
        return 'automation.trigger'; ]]]
  service_data: >
    [[[ if (window.loaction == 'path.to.home') return none;
        return 'entity_id: entity' ;]]]

btw using this to test:

      - type: custom:button-card
        show_label: true
        name: >
          [[[return hass.user]]]
        label: >
          [[[return window.location]]]

returns:
Schermafbeelding 2020-05-08 om 10.34.36

meaning the window.location is displayed alright, but I cant see the user.
Tbh, I am struggling with what’s written at the bottom here button-card/README.md at master · custom-cards/button-card · GitHub on the variables available inside the JS code… How do I use that? I didn’t find any example or documentation about user (or has for that matter…) must be missing the obvious, but in all my button configs, I’ve simply never encountered the need/issue

No, it’s not, you didn’t read the link. You have access to the path also directly.

Yes, you can return a complete object for hold_action. Static example:

hold_action: |
 [[[
    let res = {
      action: "call-service",
      service: "whatever"
   };
   res.service_data = {};
   res.service_data.entity_id = entity.entity_id;
   return res;
 ]]] 

correct, sorry, didnt realize it was a link to the W3school…still, it doesn’t allow finding the view name only, or the Lovelace path, as defined in the view config:

title: Test
icon: mdi:test-tube
path: test
cards:

window.location.pathname coming closest, but still returning “/lovelace/test”
so

label: >
  [[[return window.location.pathname.split('lovelace/')[1] ]]]

is needed for
Schermafbeelding 2020-05-08 om 10.51.23

now how to find the user…

wow, that’s a first for me, have to study what’s done there, and how to use the templates in that.
let and ‘res’ being the great unknowns to me…back to w3schools I fear :wink:

using the template I need, could it be something like:

        hold_action: |
         [[[
             let res = (window.location.pathname.split('lovelace/')[1] == 'home'
             ? {
                 action: "navigate",
                 navigation_path: "developer"
                 }
             : {
                 action: "call_service",
                 service: "automation.trigger",
                 service_data.entity_id: "entity.entity_id"
               }
            return res;
            );
          ]]]

I tried a standard construction with if (window.location.pathname.split('lovelace/')[1] == 'home') but got stuck declaring the let that way.
Now I am stuck returning the res…with the double ‘return’ in the template

You have to convert it to a string :wink: Remember how I always tell you that you need to learn these damn languages so you can do things on your own?

String(window.location.pathname).split('lovelace/')[1]

Petro, he speak with forked tongue

:rofl: :joy: :rofl: :joy:

You are a bit harsh on me here, I am trying to do something I haven’t seen any example of yet…
and btw,

        label: >
          [[[let res = window.location.pathname.split('lovelace/')[1];
             return res ]]]

works just fine…

its the template for the hold action based on this value I cant get right

Lol, CSS is the ONLY exception! Although I’d have to admit that I’ve learned a lot about it in recent months.

That’s the thing here. You’ve been here a LONG time. One basic element of all langauges (doesn’t matter the language) is object typing. If you take a beginner course in ANY language, you learn about this in the first 3 tutorials. I’ve been harping on you for years to take something with the amount of developing that you do and it’s clear you still haven’t.

If you get Object object in js as your returned string, that means you have an OBJECT and not a STRING. I.E. you convert the object to a string with a simple google search “convert window.location.pathname to string”.

EDIT: And just to clarify, I didn’t know how to do this and simply googled that and showed you the first result that I found.

think there is some misunderstanding goin on… what did you think I was asking? because there’s no problem getting the path(name) to the button frontend.

right now, this is my quest:

Sorry I miss interpreted the post and thought you needed the location when you needed the username.

As for your quest, you didn’t follow @RomRider’s post.

that’ declares the object as a dictionary…

which allows

So, with your knowledge. How would you declare a dictionary?

I am not sure, but this seems to pass the parser:

         [[[
             let res = (window.location.pathname.split('lovelace/')[1] == 'home'
             ? {
                 action: "navigate",
                 navigation_path: "developer"
                 }
             : {
                 action: "call_service",
                 service: "automation.trigger",
                 entity_id: "entity.entity_id"
               });
            return res;
          ]]]

haven’t tested it in my button yet, only in the inspector.

You’re declaring 2 dictionaries in your post. If that helps. And no, that wont work.

Also, is entity an object?

Yes I understand that… that is because depending on the state of the pathname, I either want to trigger the entity_id, or navigate to another view. These 2 different actions need to different dictionaries. Or so I thought…

Right, so if you’re declaring 2 dictionaries and service_data needs to be a dictionary… how would you add entity_id to it…

you’re returning a string here but it should be the value of the variable, not the string. Also you’re missing the service_data. I’ve cleaned up your code a bit.

         [[[
           let res; // let is same as var. res is just a variable name.
           if (window.location.pathname.split('lovelace/')[1] == 'home') {
             res = {
               action: "navigate",
               navigation_path: "developer"
             };
           } else {
             res = {
               action: "call-service",
               service: "automation.trigger",
               service_data: {
                 entity_id: entity.entity_id,
               }
             };
           }
           return res;
         ]]]

EDIT: Actually, it might not work (just re-looking at the button-card code right now and how I’ve handled it :smiley: But you can give it a try)

1 Like

like this?

[[[
  let res = (window.location.pathname.split('lovelace/')[1] == 'home'
  ? {
     action: "navigate",
     navigation_path: "developer"
    }
  : {
     action: "call_service",
     service: "automation.trigger",
     service_data: {
       entity_id: entity.entity_id }
       });
  return res;
]]]

–edit–
now see @romrider chiming in…

Thanks!
I started out that way but didnt know I had to start with

let res;

so tried the ternary route.

is there an advantage of doing it like this in anyway?

btw: think to have learned by now that let is a block variable and var is a global variable?