thomasloven / lovelace-state-switch

🔹Dynamically replace lovelace cards depending on occasion
MIT License
382 stars 27 forks source link

Custom element doesn't exist #86

Open jcwillox opened 2 years ago

jcwillox commented 2 years ago

I have an issue when using state-switch with custom cards, where sometimes it fails the load the card and displays nothing.

I've managed to narrow down the issue. Basically the custom card has not been registered initially so, HA returns a hidden error card, once the custom card is registered HA, cancels the timeout which would have shown the error card and fires an ll-rebuild event on the error-card it returned. For whatever reason, it appears that this is never received so the error-card remains hidden and is not replaced with the correct card. Firing the ll-rebuild event manually on the error-card later makes the card appear.

With that and given the inconsistency of the issue, my guess is its some sort of race condition. I'll try debugging this further, but though I'd open an issue and see if its not just me.

Version: 1.9.5 Error: Custom element doesn't exist: mushroom-chips-card.

image

jcwillox commented 1 year ago

I've figured out the issue, and it seems to be related to a change in how the frontend handles lazy-loaded cards.

I believe we used to be able to use createCardElement without having issues with the ll-rebuild event, however, inspecting the frontend code for several cards, e.g. conditional, vertical-stack, they all handle the ll-rebuild event themselves manually.

The function of most interest is the _rebuildCard in that second link, which manually replaces the dom element with the actual card once loaded.

https://github.com/home-assistant/frontend/blob/dev/src/panels/lovelace/components/hui-conditional-base.ts#L43-L69

https://github.com/home-assistant/frontend/blob/dev/src/panels/lovelace/cards/hui-conditional-card.ts#L39-L61

I did try merging the _rebuildCard function into state-switch and it seemed to fix the issue, however, given the inconsistency in reproducing this issue it needs more testing.

I also found a work around, by wrapping whatever card is having the issue with a vertical-stack card, state-switch won't need to lazy load it and the vertical-stack card can handle lazy-loading the actual card correctly.

Technically vertical-stack is lazy-loaded so we wrap state-switch in a vertical-stack to ensure it's always loaded before state-switch, something like the entities card doesn't need this as it's not lazy-loaded.

image

type: vertical-stack
cards:
  - type: custom:state-switch
    entity: user
    states:
      Admin:
        type: vertical-stack
        cards:
          - type: custom:mushroom-chips-card
            chips:
              # ...
ScottG489 commented 7 months ago

Thanks for doing a deep dive into this. I've had this issue forever.

I'm not sure I quite understand your workaround, though. I understand correctly, the problem is that state-switch isn't handling the lazy loading properly. So when it tries to render it's nested cards (like custom:mushroom-chips-card) it's possible that custom card isn't loaded yet so it needs to retry rendering that card later.

So the workaround is to use a built-in card like vertical-stack that is guaranteed to be loaded already AND handles lazy loading its nested cards properly. state-switch will try to load vertical-stack, which will handle lazy loading something like the chips card properly.

What I don't understand is why you need to wrap everything in veritical-stack?

After typing this all up, I think what I don't understand is why you're saying vertical-stack is lazy loaded. Why would it be if it's a built in card?