diff --git a/src/components/ha-control-select-menu.ts b/src/components/ha-control-select-menu.ts index 7f48497f68..2bf22046e7 100644 --- a/src/components/ha-control-select-menu.ts +++ b/src/components/ha-control-select-menu.ts @@ -1,5 +1,6 @@ import { SelectBase } from "@material/mwc-select/mwc-select-base"; import { mdiMenuDown } from "@mdi/js"; +import type { PropertyValues } from "lit"; import { css, html, nothing } from "lit"; import { customElement, property, query } from "lit/decorators"; import { classMap } from "lit/directives/class-map"; @@ -24,6 +25,16 @@ export class HaControlSelectMenu extends SelectBase { @property({ type: Boolean, attribute: "hide-label" }) public hideLabel = false; + @property() public options; + + protected updated(changedProps: PropertyValues) { + super.updated(changedProps); + if (changedProps.get("options")) { + this.layoutOptions(); + this.selectByValue(this.value); + } + } + public override render() { const classes = { "select-disabled": this.disabled, diff --git a/src/components/ha-select.ts b/src/components/ha-select.ts index f856f0edd1..7f240ee525 100644 --- a/src/components/ha-select.ts +++ b/src/components/ha-select.ts @@ -17,6 +17,8 @@ export class HaSelect extends SelectBase { @property({ attribute: "inline-arrow", type: Boolean }) public inlineArrow = false; + @property() public options; + protected override render() { return html` ${super.render()} @@ -68,6 +70,10 @@ export class HaSelect extends SelectBase { textContainerElement?.classList.remove("inline-arrow"); } } + if (changedProperties.get("options")) { + this.layoutOptions(); + this.selectByValue(this.value); + } } disconnectedCallback() { diff --git a/src/panels/lovelace/card-features/hui-select-options-card-feature.ts b/src/panels/lovelace/card-features/hui-select-options-card-feature.ts index 3c5619557b..65ee578b54 100644 --- a/src/panels/lovelace/card-features/hui-select-options-card-feature.ts +++ b/src/panels/lovelace/card-features/hui-select-options-card-feature.ts @@ -2,6 +2,7 @@ import type { HassEntity } from "home-assistant-js-websocket"; import type { PropertyValues } from "lit"; import { html, LitElement, nothing } from "lit"; import { customElement, property, query, state } from "lit/decorators"; +import memoizeOne from "memoize-one"; import { stopPropagation } from "../../../common/dom/stop_propagation"; import { computeDomain } from "../../../common/entity/compute_domain"; import "../../../components/ha-control-select-menu"; @@ -84,7 +85,11 @@ class HuiSelectOptionsCardFeature const oldOption = this.stateObj!.state; - if (option === oldOption) return; + if ( + option === oldOption || + !this.stateObj!.attributes.options.includes(option) + ) + return; this._currentOption = option; @@ -115,7 +120,7 @@ class HuiSelectOptionsCardFeature const stateObj = this.stateObj; - const options = filterModes( + const options = this._getOptions( this.stateObj.attributes.options, this._config.options ); @@ -126,6 +131,7 @@ class HuiSelectOptionsCardFeature hide-label .label=${this.hass.localize("ui.card.select.option")} .value=${stateObj.state} + .options=${options} .disabled=${this.stateObj.state === UNAVAILABLE} fixedMenuPosition naturalMenuWidth @@ -143,6 +149,11 @@ class HuiSelectOptionsCardFeature `; } + private _getOptions = memoizeOne( + (attributeOptions: string[], configOptions: string[] | undefined) => + filterModes(attributeOptions, configOptions) + ); + static get styles() { return cardFeatureStyles; } diff --git a/src/panels/lovelace/entity-rows/hui-input-select-entity-row.ts b/src/panels/lovelace/entity-rows/hui-input-select-entity-row.ts index 9a256e6e48..95e2ddebff 100644 --- a/src/panels/lovelace/entity-rows/hui-input-select-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-input-select-entity-row.ts @@ -1,11 +1,10 @@ import "@material/mwc-list/mwc-list-item"; import type { PropertyValues } from "lit"; import { css, html, LitElement, nothing } from "lit"; -import { customElement, property, query, state } from "lit/decorators"; +import { customElement, property, state } from "lit/decorators"; import { stopPropagation } from "../../../common/dom/stop_propagation"; import { computeStateName } from "../../../common/entity/compute_state_name"; import "../../../components/ha-select"; -import type { HaSelect } from "../../../components/ha-select"; import { UNAVAILABLE } from "../../../data/entity"; import { forwardHaptic } from "../../../data/haptics"; import type { InputSelectEntity } from "../../../data/input_select"; @@ -23,8 +22,6 @@ class HuiInputSelectEntityRow extends LitElement implements LovelaceRow { @state() private _config?: EntitiesCardEntityConfig; - @query("ha-select") private _haSelect!: HaSelect; - public setConfig(config: EntitiesCardEntityConfig): void { if (!config || !config.entity) { throw new Error("Entity must be specified"); @@ -37,28 +34,6 @@ class HuiInputSelectEntityRow extends LitElement implements LovelaceRow { return hasConfigOrEntityChanged(this, changedProps); } - protected updated(changedProps: PropertyValues) { - super.updated(changedProps); - if (!this._config) { - return; - } - if (changedProps.has("hass")) { - const oldHass = changedProps.get("hass"); - const stateObj = this.hass?.states[this._config.entity] as - | InputSelectEntity - | undefined; - const oldStateObj = oldHass?.states[this._config.entity] as - | InputSelectEntity - | undefined; - if ( - stateObj && - stateObj.attributes.options !== oldStateObj?.attributes.options - ) { - this._haSelect.layoutOptions(); - } - } - } - protected render() { if (!this.hass || !this._config) { return nothing; @@ -85,6 +60,7 @@ class HuiInputSelectEntityRow extends LitElement implements LovelaceRow {