diff --git a/gallery/src/pages/components/ha-selector.ts b/gallery/src/pages/components/ha-selector.ts index 053c95d7da..3a456cae66 100644 --- a/gallery/src/pages/components/ha-selector.ts +++ b/gallery/src/pages/components/ha-selector.ts @@ -164,9 +164,24 @@ const SCHEMAS: { }, }, object: { name: "Object", selector: { object: {} } }, + select_radio: { + name: "Select (Radio)", + selector: { select: { options: ["Option 1", "Option 2"] } }, + }, select: { name: "Select", - selector: { select: { options: ["Option 1", "Option 2"] } }, + selector: { + select: { + options: [ + "Option 1", + "Option 2", + "Option 3", + "Option 4", + "Option 5", + "Option 6", + ], + }, + }, }, icon: { name: "Icon", selector: { icon: {} } }, media: { name: "Media", selector: { media: {} } }, diff --git a/src/components/ha-form/ha-form-select.ts b/src/components/ha-form/ha-form-select.ts index 2e342a39a2..73dc74b95c 100644 --- a/src/components/ha-form/ha-form-select.ts +++ b/src/components/ha-form/ha-form-select.ts @@ -1,16 +1,20 @@ -import "@material/mwc-list/mwc-list-item"; -import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; -import { customElement, property, query } from "lit/decorators"; +import memoizeOne from "memoize-one"; +import { html, LitElement, TemplateResult } from "lit"; +import { customElement, property } from "lit/decorators"; import { fireEvent } from "../../common/dom/fire_event"; -import { stopPropagation } from "../../common/dom/stop_propagation"; -import "../ha-radio"; -import type { HaRadio } from "../ha-radio"; -import "../ha-select"; -import type { HaSelect } from "../ha-select"; -import { HaFormElement, HaFormSelectData, HaFormSelectSchema } from "./types"; +import type { HomeAssistant } from "../../types"; +import type { + HaFormElement, + HaFormSelectData, + HaFormSelectSchema, +} from "./types"; +import type { SelectSelector } from "../../data/selector"; +import "../ha-selector/ha-selector-select"; @customElement("ha-form-select") export class HaFormSelect extends LitElement implements HaFormElement { + @property({ attribute: false }) public hass!: HomeAssistant; + @property({ attribute: false }) public schema!: HaFormSelectSchema; @property() public data!: HaFormSelectData; @@ -19,60 +23,35 @@ export class HaFormSelect extends LitElement implements HaFormElement { @property({ type: Boolean }) public disabled = false; - @query("ha-select", true) private _input?: HTMLElement; - - public focus() { - if (this._input) { - this._input.focus(); - } - } + private _selectSchema = memoizeOne( + (options): SelectSelector => ({ + select: { + options: options.map((option) => ({ + value: option[0], + label: option[1], + })), + }, + }) + ); protected render(): TemplateResult { - if (this.schema.required && this.schema.options!.length < 6) { - return html` -
- ${this.label} - ${this.schema.options.map( - ([value, label]) => html` - - - - ` - )} -
- `; - } - return html` - - ${!this.schema.required - ? html`` - : ""} - ${this.schema.options!.map( - ([value, label]) => html` - ${label} - ` - )} - + .required=${this.schema.required} + .selector=${this._selectSchema(this.schema.options)} + @value-changed=${this._valueChanged} + > `; } private _valueChanged(ev: CustomEvent) { ev.stopPropagation(); - let value: string | undefined = (ev.target as HaSelect | HaRadio).value; + let value: string | undefined = ev.detail.value; if (value === this.data) { return; @@ -86,15 +65,6 @@ export class HaFormSelect extends LitElement implements HaFormElement { value, }); } - - static get styles(): CSSResultGroup { - return css` - ha-select, - mwc-formfield { - display: block; - } - `; - } } declare global { diff --git a/src/components/ha-selector/ha-selector-select.ts b/src/components/ha-selector/ha-selector-select.ts index ebc2704992..96cc114483 100644 --- a/src/components/ha-selector/ha-selector-select.ts +++ b/src/components/ha-selector/ha-selector-select.ts @@ -1,17 +1,19 @@ +import "@material/mwc-formfield/mwc-formfield"; import "@material/mwc-list/mwc-list-item"; import { css, CSSResultGroup, html, LitElement } from "lit"; import { customElement, property } from "lit/decorators"; import { fireEvent } from "../../common/dom/fire_event"; import { stopPropagation } from "../../common/dom/stop_propagation"; -import { SelectOption, SelectSelector } from "../../data/selector"; -import { HomeAssistant } from "../../types"; +import type { SelectOption, SelectSelector } from "../../data/selector"; +import type { HomeAssistant } from "../../types"; import "../ha-select"; +import "../ha-radio"; @customElement("ha-selector-select") export class HaSelectSelector extends LitElement { - @property() public hass!: HomeAssistant; + @property({ attribute: false }) public hass!: HomeAssistant; - @property() public selector!: SelectSelector; + @property({ attribute: false }) public selector!: SelectSelector; @property() public value?: string; @@ -21,24 +23,51 @@ export class HaSelectSelector extends LitElement { @property({ type: Boolean }) public disabled = false; - protected render() { - return html` - ${this.selector.select.options.map((item: string | SelectOption) => { - const value = typeof item === "object" ? item.value : item; - const label = typeof item === "object" ? item.label : item; + @property({ type: Boolean }) public required = true; - return html`${label}`; - })} - `; + protected render() { + if (this.required && this.selector.select.options!.length < 6) { + return html` +
+ ${this.label} + ${this.selector.select.options.map((item: string | SelectOption) => { + const value = typeof item === "object" ? item.value : item; + const label = typeof item === "object" ? item.label : item; + + return html` + + + + `; + })} +
+ `; + } + + return html` + + ${this.selector.select.options.map((item: string | SelectOption) => { + const value = typeof item === "object" ? item.value : item; + const label = typeof item === "object" ? item.label : item; + + return html`${label}`; + })} + + `; } private _valueChanged(ev) { @@ -56,6 +85,9 @@ export class HaSelectSelector extends LitElement { ha-select { width: 100%; } + mwc-formfield { + display: block; + } `; } }