diff --git a/src/common/dom/stop_propagation.ts b/src/common/dom/stop_propagation.ts
new file mode 100644
index 0000000000..b04b2156c0
--- /dev/null
+++ b/src/common/dom/stop_propagation.ts
@@ -0,0 +1 @@
+export const stopPropagation = (ev) => ev.stopPropagation();
diff --git a/src/data/input-select.ts b/src/data/input-select.ts
index 04a2176fa5..c119cd0290 100644
--- a/src/data/input-select.ts
+++ b/src/data/input-select.ts
@@ -1,6 +1,6 @@
import { HomeAssistant } from "../types";
-export const setOption = (
+export const setInputSelectOption = (
hass: HomeAssistant,
entity: string,
option: string
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 c068fe3179..3568196454 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
@@ -8,7 +8,6 @@ import {
customElement,
PropertyValues,
} from "lit-element";
-import { repeat } from "lit-html/directives/repeat";
import "@polymer/paper-item/paper-item";
import "@polymer/paper-listbox/paper-listbox";
@@ -18,11 +17,12 @@ import "../components/hui-warning";
import computeStateName from "../../../common/entity/compute_state_name";
-import { HomeAssistant } from "../../../types";
+import { HomeAssistant, InputSelectEntity } from "../../../types";
import { EntityRow, EntityConfig } from "./types";
-import { setOption } from "../../../data/input-select";
+import { setInputSelectOption } from "../../../data/input-select";
import { hasConfigOrEntityChanged } from "../common/has-changed";
import { forwardHaptic } from "../../../util/haptics";
+import { stopPropagation } from "../../../common/dom/stop_propagation";
@customElement("hui-input-select-entity-row")
class HuiInputSelectEntityRow extends LitElement implements EntityRow {
@@ -47,7 +47,9 @@ class HuiInputSelectEntityRow extends LitElement implements EntityRow {
return html``;
}
- const stateObj = this.hass.states[this._config.entity];
+ const stateObj = this.hass.states[this._config.entity] as
+ | InputSelectEntity
+ | undefined;
if (!stateObj) {
return html`
@@ -64,26 +66,43 @@ class HuiInputSelectEntityRow extends LitElement implements EntityRow {
return html`
-
- ${repeat(
- stateObj.attributes.options,
- (option) =>
- html`
- ${option}
- `
+
+ ${stateObj.attributes.options.map(
+ (option) => html`
+ ${option}
+ `
)}
`;
}
+ protected updated(changedProps: PropertyValues) {
+ super.updated(changedProps);
+
+ if (!this.hass || !this._config) {
+ return;
+ }
+
+ const stateObj = this.hass.states[this._config.entity] as
+ | InputSelectEntity
+ | undefined;
+
+ if (!stateObj) {
+ return;
+ }
+
+ // Update selected after rendering the items or else it won't work in Firefox
+ this.shadowRoot!.querySelector(
+ "paper-listbox"
+ )!.selected = stateObj.attributes.options.indexOf(stateObj.state);
+ }
+
static get styles(): CSSResult {
return css`
:host {
@@ -94,22 +113,28 @@ class HuiInputSelectEntityRow extends LitElement implements EntityRow {
margin-left: 16px;
flex: 1;
}
+
+ paper-item {
+ cursor: pointer;
+ min-width: 200px;
+ }
`;
}
private _selectedChanged(ev): void {
- forwardHaptic(this, "light");
- // Selected Option will transition to '' before transitioning to new value
const stateObj = this.hass!.states[this._config!.entity];
- if (
- !ev.target.selectedItem ||
- ev.target.selectedItem.innerText === "" ||
- ev.target.selectedItem.innerText === stateObj.state
- ) {
+ const option = ev.detail.item.innerText;
+ if (option === stateObj.state) {
return;
}
- setOption(this.hass!, stateObj.entity_id, ev.target.selectedItem.innerText);
+ forwardHaptic(this, "light");
+
+ setInputSelectOption(
+ this.hass!,
+ stateObj.entity_id,
+ ev.target.selectedItem.innerText
+ );
}
}
diff --git a/src/polymer-types.ts b/src/polymer-types.ts
index 4432149176..4ffbf77df6 100644
--- a/src/polymer-types.ts
+++ b/src/polymer-types.ts
@@ -18,6 +18,12 @@ export interface PolymerChangedEvent extends Event {
};
}
+export interface PolymerIronSelectEvent extends Event {
+ detail: {
+ item: T;
+ };
+}
+
declare global {
// for fire event
interface HASSDomEvents {
diff --git a/src/state-summary/state-card-input_select.js b/src/state-summary/state-card-input_select.js
deleted file mode 100644
index 76e4667988..0000000000
--- a/src/state-summary/state-card-input_select.js
+++ /dev/null
@@ -1,96 +0,0 @@
-import "@polymer/paper-dropdown-menu/paper-dropdown-menu";
-import "@polymer/paper-item/paper-item";
-import "@polymer/paper-listbox/paper-listbox";
-import { html } from "@polymer/polymer/lib/utils/html-tag";
-import { PolymerElement } from "@polymer/polymer/polymer-element";
-
-import "../components/entity/state-badge";
-
-import computeStateName from "../common/entity/compute_state_name";
-
-class StateCardInputSelect extends PolymerElement {
- static get template() {
- return html`
-
-
- ${this.stateBadgeTemplate}
-
-
-
- [[item]]
-
-
-
- `;
- }
-
- static get stateBadgeTemplate() {
- return html`
-
- `;
- }
-
- static get properties() {
- return {
- hass: Object,
- stateObj: Object,
- inDialog: {
- type: Boolean,
- value: false,
- },
- selectedOption: {
- type: String,
- observer: "selectedOptionChanged",
- },
- };
- }
-
- _computeStateName(stateObj) {
- return computeStateName(stateObj);
- }
-
- computeSelected(stateObj) {
- return stateObj.attributes.options.indexOf(stateObj.state);
- }
-
- selectedOptionChanged(option) {
- // Selected Option will transition to '' before transitioning to new value
- if (option === "" || option === this.stateObj.state) {
- return;
- }
- this.hass.callService("input_select", "select_option", {
- option: option,
- entity_id: this.stateObj.entity_id,
- });
- }
-
- stopPropagation(ev) {
- ev.stopPropagation();
- }
-}
-customElements.define("state-card-input_select", StateCardInputSelect);
diff --git a/src/state-summary/state-card-input_select.ts b/src/state-summary/state-card-input_select.ts
new file mode 100644
index 0000000000..19befdfb29
--- /dev/null
+++ b/src/state-summary/state-card-input_select.ts
@@ -0,0 +1,96 @@
+import {
+ LitElement,
+ customElement,
+ TemplateResult,
+ html,
+ CSSResult,
+ css,
+ property,
+ PropertyValues,
+} from "lit-element";
+import "@polymer/paper-dropdown-menu/paper-dropdown-menu-light";
+import "@polymer/paper-item/paper-item";
+// tslint:disable-next-line: no-duplicate-imports
+import { PaperItemElement } from "@polymer/paper-item/paper-item";
+import "@polymer/paper-listbox/paper-listbox";
+
+import "../components/entity/state-badge";
+
+import computeStateName from "../common/entity/compute_state_name";
+import { HomeAssistant, InputSelectEntity } from "../types";
+import { setInputSelectOption } from "../data/input-select";
+import { PolymerIronSelectEvent } from "../polymer-types";
+import { stopPropagation } from "../common/dom/stop_propagation";
+
+@customElement("state-card-input_select")
+class StateCardInputSelect extends LitElement {
+ @property() public hass!: HomeAssistant;
+ @property() public stateObj!: InputSelectEntity;
+
+ protected render(): TemplateResult | void {
+ return html`
+
+
+
+ ${this.stateObj.attributes.options.map(
+ (option) => html`
+ ${option}
+ `
+ )}
+
+
+ `;
+ }
+
+ protected updated(changedProps: PropertyValues) {
+ super.updated(changedProps);
+ // Update selected after rendering the items or else it won't work in Firefox
+ this.shadowRoot!.querySelector(
+ "paper-listbox"
+ )!.selected = this.stateObj.attributes.options.indexOf(this.stateObj.state);
+ }
+
+ private async _selectedOptionChanged(
+ ev: PolymerIronSelectEvent
+ ) {
+ const option = ev.detail.item.innerText;
+ if (option === this.stateObj.state) {
+ return;
+ }
+ await setInputSelectOption(this.hass, this.stateObj.entity_id, option);
+ }
+
+ static get styles(): CSSResult {
+ return css`
+ :host {
+ display: block;
+ }
+
+ state-badge {
+ float: left;
+ margin-top: 10px;
+ }
+
+ paper-dropdown-menu-light {
+ display: block;
+ margin-left: 53px;
+ }
+
+ paper-item {
+ cursor: pointer;
+ min-width: 200px;
+ }
+ `;
+ }
+}
+
+declare global {
+ interface HTMLElementTagNameMap {
+ "state-card-input_select": StateCardInputSelect;
+ }
+}
diff --git a/src/types.ts b/src/types.ts
index e312a1f6b9..9a5a731a3b 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -219,6 +219,12 @@ export type CameraEntity = HassEntityBase & {
};
};
+export type InputSelectEntity = HassEntityBase & {
+ attributes: HassEntityAttributeBase & {
+ options: string[];
+ };
+};
+
export interface Route {
prefix: string;
path: string;