Clooos / Bubble-Card

Bubble Card is a minimalist card collection for Home Assistant with a nice pop-up touch.
MIT License
2.1k stars 65 forks source link

`${card.querySelector()} ` not working on initial page load, but works after a state change on any bubble card #975

Open quincarter opened 1 day ago

quincarter commented 1 day ago

For any feature request you can open a new discussion here:
https://github.com/Clooos/Bubble-Card/discussions/categories/feature-requests

For any question you can open a new discussion here:
https://github.com/Clooos/Bubble-Card/discussions/categories/q-a

Describe the bug
When the same hass.states[].state is used multiple times in a style template, the second time doesn't always resolve properly. For example when I try to listen to the do not disturb sensor on my phone, i want to change the bubble button color and set the text for the bubble name to say Quin is on DND - This works if i am already on the home assistant dashboard then it works fine, but when i reload the page, the color resolves but the text does not, and it shows my default name variable.

*****EDIT --- I think the bug has to do with the card.querySelector() and when it is going off. The element isn't selectable on the initial page load. That's why the colors are working but not the nested JS stuff.

Expected behavior
*.querySelector() should work on initial load so that button states and names can be resolved for anything custom that is being overwritten for customization

Screenshots

Screenshot 2024-12-01 at 6 43 17 PM

YAML

.bubble-button-background {
    opacity: 0.5 !important;
    background-color: ${state === 'home' ? 'green' : 'red'} !important;
  }

.bubble-button-background {
    opacity: 0.5 !important;
    background-color: ${hass.states['sensor.quin_s_pixel_9_pro_xl_do_not_disturb_sensor'].state === 'priority_only' ? 'lightgrey' : ''} !important;
  }

.bubble-button-background {
    opacity: 0.5 !important;
    background-color: ${hass.states['binary_sensor.quin_s_pixel_9_pro_xl_android_auto'].state === 'on' ? 'rebeccapurple' : ''} !important;
  }

.bubble-sub-button {
    background-color: transparent !important;
  }

.bubble-sub-button-1 {
    display: ${(hass.states['sensor.quin_s_pixel_9_pro_xl_battery_state'].state === 'charging' || hass.states['sensor.quin_s_pixel_9_pro_xl_battery_state'].state === 'full')  && hass.states['binary_sensor.quin_s_pixel_9_pro_xl_android_auto'].state !== 'on' ? '' : 'none'} !important;
  }

.bubble-sub-button-2 {
    display: ${hass.states['binary_sensor.quin_s_pixel_9_pro_xl_android_auto'].state === 'on' ? '' : 'none'} !important;
  }

/* this one doesn't ever fire on initial load unless another change is fired */
${hass.states['sensor.quin_s_pixel_9_pro_xl_do_not_disturb_sensor'].state === 'priority_only' ? card.querySelector('.bubble-name').innerText = "Quin is on DND" : card.querySelector('.bubble-name').innerText = "Quin"}

Full button code

type: custom:bubble-card
card_type: button
button_type: state
entity: person.quin_carter
styles: >-
  .bubble-button-background {
      opacity: 0.5 !important;
      background-color: ${state === 'home' ? 'green' : 'red'} !important;
    }

  .bubble-button-background {
      opacity: 0.5 !important;
      background-color: ${hass.states['sensor.quin_s_pixel_9_pro_xl_do_not_disturb_sensor'].state === 'priority_only' ? 'lightgrey' : ''} !important;
    }

  .bubble-button-background {
      opacity: 0.5 !important;
      background-color: ${hass.states['binary_sensor.quin_s_pixel_9_pro_xl_android_auto'].state === 'on' ? 'rebeccapurple' : ''} !important;
    }

  .bubble-sub-button {
      background-color: transparent !important;
    }

  .bubble-sub-button-1 {
      display: ${(hass.states['sensor.quin_s_pixel_9_pro_xl_battery_state'].state === 'charging' || hass.states['sensor.quin_s_pixel_9_pro_xl_battery_state'].state === 'full')  && hass.states['binary_sensor.quin_s_pixel_9_pro_xl_android_auto'].state !== 'on' ? '' : 'none'} !important;
    }

  .bubble-sub-button-2 {
      display: ${hass.states['binary_sensor.quin_s_pixel_9_pro_xl_android_auto'].state === 'on' ? '' : 'none'} !important;
    }

  ${hass.states['sensor.quin_s_pixel_9_pro_xl_do_not_disturb_sensor'].state ===
  'priority_only' ? card.querySelector('.bubble-name').innerText = "Quin is on
  DND" : card.querySelector('.bubble-name').innerText = "Quin"}
name: ""
show_attribute: false
show_last_changed: true
sub_button:
  - entity: sensor.quin_s_pixel_9_pro_xl_battery_level
    show_state: true
    show_attribute: false
    show_last_changed: false
    show_name: false
    show_icon: true
    icon: ""
  - entity: binary_sensor.quin_s_pixel_9_pro_xl_android_auto
    icon: mdi:car
button_action:
  tap_action:
    action: navigate
    navigation_path: "#person-quin"
card_layout: large

Informations (please complete the following information):

Module Version
Core 2024.11.3
Supervisor 2024.11.4
Operating System 13.2
Frontend 20241106.2
quincarter commented 1 day ago

Followup question. Can i set JS variables in the style template and reuse them?

quincarter commented 1 day ago

If i manually fire off a state change of some kind after the elements are on the screen, the items update. I think there is something wrong with how the styles are appended and looking for the card.querySelector() - i think it is returning null or undefined because the element isn't loaded quite yet. In LitElement i would just do everything in firstUpdated() and wait for the items to be appended to the screen. But looks like everything here is in connectedCallback because it is just an HTMLElement. So i think the solution would be to wait for the element to be available in the shadowDom for the querySelector to work properly on the initial load.

quincarter commented 1 day ago

Video demo showing what is happening: https://drive.google.com/file/d/1Jgd185XdMphV8jw1n9dS7wTdALtPFJjs/view?usp=sharing

quincarter commented 1 day ago

Update - when i only try to update the .bubble-name innerText on a single test button, i get this error:

image

So i know it is completely unrelated to my css stuff.

My YAML

type: custom:bubble-card
card_type: button
entity: light.my_custom_lamp
icon: mdi:lamp
show_state: true
show_last_changed: true
styles: |
  ${card.querySelector('.button-name').innerText = 'Testing123'}
quincarter commented 1 day ago

Another video showing the delay/timeout it takes for the name to update. Not sure why this is happening, honestly. I have the code pulled down but i don't know how to test it in HA to get an idea of how to fix it.

https://drive.google.com/file/d/1gQdOixLgXnOGnwQxbnQahRJqh4JPL6Tq/view?usp=sharing

Clooos commented 3 hours ago

Hi! For your error in your previous comment, you don't use the correct class, it's .bubble-name and not .button-name.

I will check if I can reproduce your initial issue.

Clooos commented 3 hours ago

I was able to reproduce it and indeed it was only an issue when card.querySelector('.bubble-name').innerText was used, I say "was" because this is now fixed on my side, just wait for the next release now 🙂

quincarter commented 2 hours ago

Hi! For your error in your previous comment, you don't use the correct class, it's .bubble-name and not .button-name.

I will check if I can reproduce your initial issue.

Yeah I actually solved the class error.

quincarter commented 2 hours ago

I was able to reproduce it and indeed it was only an issue when card.querySelector('.bubble-name').innerText was used, I say "was" because this is now fixed on my side, just wait for the next release now 🙂

Nice! Can you possibly reference this issue so I can review what you did update it? I'm really interested how you handled that with the HTMLElement inside of HA.

Also, can you add contribution instructions to your readme? I would love to be able to contribute to the project, but I've never built a front-end plug-in for home assistant before. So I don't even know how to get started with contribution or testing in my setup. I'm a frontend developer and would really like to be able to contribute to a cool project in FOSS and this one is pretty cool.

Clooos commented 2 hours ago

Indeed I should clarify this, in fact you "just" need to install Webpack to build the sources, there is a config file at the root of the GitHub repo, just use it then you're all good. I've configured it so that it send the updated js file to my HA server each time that I save, I've also disabled the cache in my browser for Home Assistant.

And your help would be more than welcome, working on this project just by myself is not always the easiest task! 😃

Clooos commented 2 hours ago

And this is the only solution I found to fix this 👀

image

I also tried updating the custom styles before the name but that don't work for some reason 🤔

quincarter commented 2 hours ago

You may want to variabilize that class name or the selector name that you're passing into the query selector function. Then it'll work for whatever you pass into it maybe?

Clooos commented 2 hours ago

I don't know, I will not try other ways for now (I'm truly tired, and I will have less time for some days), but don't hesitate to give it a look! If you have any questions, don't hesitate to ask them! 😄

And to be honest I've started Bubble Card as a way to learn JS, I'm not an experienced developer even if I've learned a lot by myself in a year with this project. So some of my approaches are probably not the most optimized ones.

quincarter commented 2 hours ago

I will take a look! You've done a great job!