Skip to content

Commit

Permalink
Don't set hass to undefined in lovelace cards. (#21189)
Browse files Browse the repository at this point in the history
* Wait for hass and config before building the card

* Don't use setter

* Improve code readability

* Use hasupdated

* Rename build to load
  • Loading branch information
piitaya authored Jun 27, 2024
1 parent 7aa005e commit 7603fa3
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 43 deletions.
90 changes: 48 additions & 42 deletions src/panels/lovelace/cards/hui-card.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { PropertyValueMap, PropertyValues, ReactiveElement } from "lit";
import { PropertyValues, ReactiveElement } from "lit";
import { customElement, property } from "lit/decorators";
import { fireEvent } from "../../../common/dom/fire_event";
import { MediaQueriesListener } from "../../../common/dom/media_query";
Expand All @@ -23,29 +23,20 @@ declare global {

@customElement("hui-card")
export class HuiCard extends ReactiveElement {
@property({ attribute: false }) public hass?: HomeAssistant;

@property({ type: Boolean }) public preview = false;

@property({ type: Boolean }) public isPanel = false;

set config(config: LovelaceCardConfig | undefined) {
if (!config) return;
if (config.type !== this._config?.type) {
this._buildElement(config);
} else if (config !== this.config) {
this._element?.setConfig(config);
fireEvent(this, "card-updated");
}
this._config = config;
}
@property({ attribute: false }) public config?: LovelaceCardConfig;

@property({ attribute: false })
public get config() {
return this._config;
}
@property({ attribute: false }) public hass?: HomeAssistant;

private _config?: LovelaceCardConfig;
public load() {
if (!this.config) {
throw new Error("Cannot build card without config");
}
this._loadElement(this.config);
}

private _element?: LovelaceCard;

Expand Down Expand Up @@ -90,57 +81,76 @@ export class HuiCard extends ReactiveElement {
return this._element?.getLayoutOptions?.() ?? {};
}

private _createElement(config: LovelaceCardConfig) {
const element = createCardElement(config);
element.hass = this.hass;
element.preview = this.preview;
private _loadElement(config: LovelaceCardConfig) {
this._element = createCardElement(config);
if (this.hass) {
this._element.hass = this.hass;
}
this._element.preview = this.preview;
// For backwards compatibility
(element as any).editMode = this.preview;
(this._element as any).editMode = this.preview;
// Update element when the visibility of the card changes (e.g. conditional card or filter card)
element.addEventListener("card-visibility-changed", (ev: Event) => {
this._element.addEventListener("card-visibility-changed", (ev: Event) => {
ev.stopPropagation();
this._updateVisibility();
});
element.addEventListener(
this._element.addEventListener(
"ll-upgrade",
(ev: Event) => {
ev.stopPropagation();
element.hass = this.hass;
element.preview = this.preview;
if (this.hass) {
this._element!.hass = this.hass;
}
fireEvent(this, "card-updated");
},
{ once: true }
);
element.addEventListener(
this._element.addEventListener(
"ll-rebuild",
(ev: Event) => {
ev.stopPropagation();
this._buildElement(config);
this._loadElement(config);
fireEvent(this, "card-updated");
},
{ once: true }
);
return element;
}

private _buildElement(config: LovelaceCardConfig) {
this._element = this._createElement(config);

while (this.lastChild) {
this.removeChild(this.lastChild);
}
this._updateVisibility();
}

protected willUpdate(changedProps: PropertyValues<typeof this>): void {
super.willUpdate(changedProps);

if (!this._element) {
this.load();
}
}

protected update(changedProps: PropertyValues<typeof this>) {
super.update(changedProps);

if (this._element) {
if (changedProps.has("config") && this.hasUpdated) {
const oldConfig = changedProps.get("config");
if (this.config !== oldConfig && this.config) {
const typeChanged = this.config?.type !== oldConfig?.type;
if (typeChanged) {
this._loadElement(this.config);
} else {
this._element?.setConfig(this.config);
fireEvent(this, "card-updated");
}
}
}
if (changedProps.has("hass")) {
try {
this._element.hass = this.hass;
if (this.hass) {
this._element.hass = this.hass;
}
} catch (e: any) {
this._buildElement(createErrorCardConfig(e.message, null));
this._loadElement(createErrorCardConfig(e.message, null));
}
}
if (changedProps.has("preview")) {
Expand All @@ -149,18 +159,14 @@ export class HuiCard extends ReactiveElement {
// For backwards compatibility
(this._element as any).editMode = this.preview;
} catch (e: any) {
this._buildElement(createErrorCardConfig(e.message, null));
this._loadElement(createErrorCardConfig(e.message, null));
}
}
if (changedProps.has("isPanel")) {
this._element.isPanel = this.isPanel;
}
}
}

protected willUpdate(
changedProps: PropertyValueMap<any> | Map<PropertyKey, unknown>
): void {
if (changedProps.has("hass") || changedProps.has("preview")) {
this._updateVisibility();
}
Expand Down
1 change: 1 addition & 0 deletions src/panels/lovelace/cards/hui-conditional-card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class HuiConditionalCard extends HuiConditionalBase implements LovelaceCard {
element.hass = this.hass;
element.preview = this.preview;
element.config = cardConfig;
element.load();
return element;
}

Expand Down
1 change: 1 addition & 0 deletions src/panels/lovelace/cards/hui-entity-filter-card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ export class HuiEntityFilterCard
element.hass = this.hass;
element.preview = this.preview;
element.config = cardConfig;
element.load();
return element;
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/panels/lovelace/cards/hui-stack-card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export abstract class HuiStackCard<T extends StackCardConfig = StackCardConfig>
card.hass = this.hass;
});
}
if (changedProperties.has("editMode")) {
if (changedProperties.has("preview")) {
this._cards.forEach((card) => {
card.preview = this.preview;
});
Expand All @@ -69,6 +69,7 @@ export abstract class HuiStackCard<T extends StackCardConfig = StackCardConfig>
element.hass = this.hass;
element.preview = this.preview;
element.config = cardConfig;
element.load();
return element;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ export class HuiCardLayoutEditor extends LitElement {
this._defaultLayoutOptions =
this._cardElement?.getElementLayoutOptions();
});
this._cardElement.load();
this._defaultLayoutOptions = this._cardElement.getElementLayoutOptions();
} catch (err) {
// eslint-disable-next-line no-console
Expand Down
1 change: 1 addition & 0 deletions src/panels/lovelace/sections/hui-section.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export class HuiSection extends ReactiveElement {
ev.stopPropagation();
this._cards = [...this._cards];
});
element.load();
return element;
}

Expand Down
1 change: 1 addition & 0 deletions src/panels/lovelace/views/hui-view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ export class HUIView extends ReactiveElement {
ev.stopPropagation();
this._cards = [...this._cards];
});
element.load();
return element;
}

Expand Down

0 comments on commit 7603fa3

Please sign in to comment.