diff --git a/gallery/src/pages/components/ha-selector.ts b/gallery/src/pages/components/ha-selector.ts
index 600176d024..c3855147ed 100644
--- a/gallery/src/pages/components/ha-selector.ts
+++ b/gallery/src/pages/components/ha-selector.ts
@@ -175,6 +175,12 @@ const SCHEMAS: {
},
},
},
+ {
+ name: "Multiples",
+ input: {
+ entity: { name: "Entity", selector: { entity: { multiple: true } } },
+ },
+ },
];
@customElement("demo-components-ha-selector")
diff --git a/src/components/ha-selector/ha-selector-entity.ts b/src/components/ha-selector/ha-selector-entity.ts
index 566dfc0a45..36d0ce57ad 100644
--- a/src/components/ha-selector/ha-selector-entity.ts
+++ b/src/components/ha-selector/ha-selector-entity.ts
@@ -1,6 +1,8 @@
import { HassEntity, UnsubscribeFunc } from "home-assistant-js-websocket";
-import { html, LitElement } from "lit";
+import { css, html, LitElement } from "lit";
import { customElement, property, state } from "lit/decorators";
+import { repeat } from "lit/directives/repeat";
+import { fireEvent } from "../../common/dom/fire_event";
import { computeStateDomain } from "../../common/entity/compute_state_domain";
import { subscribeEntityRegistry } from "../../data/entity_registry";
import { EntitySelector } from "../../data/selector";
@@ -23,14 +25,45 @@ export class HaEntitySelector extends SubscribeMixin(LitElement) {
@property({ type: Boolean }) public disabled = false;
protected render() {
- return html``;
+ if (!this.selector.entity.multiple) {
+ return html``;
+ }
+
+ // For multiple, the value is a list.
+ const value = this._normalizedValue as string[];
+
+ return html`
+ ${this.label ? html`
${this.label}
` : ""}
+ ${repeat(
+ value,
+ (val) => val,
+ (entityId, index) => html`
+
+ `
+ )}
+
+ `;
}
public hassSubscribe(): UnsubscribeFunc[] {
@@ -48,6 +81,17 @@ export class HaEntitySelector extends SubscribeMixin(LitElement) {
];
}
+ private get _normalizedValue() {
+ if (!this.selector.entity.multiple) {
+ return this.value;
+ }
+
+ if (!this.value) {
+ return [];
+ }
+ return Array.isArray(this.value) ? this.value : [this.value];
+ }
+
private _filterEntities = (entity: HassEntity): boolean => {
if (this.selector.entity?.domain) {
const filterDomain = this.selector.entity.domain;
@@ -79,6 +123,43 @@ export class HaEntitySelector extends SubscribeMixin(LitElement) {
}
return true;
};
+
+ // this method is only used when multiple: true
+ private _valueChanged(ev: any) {
+ ev.stopPropagation();
+
+ // undefined = new value
+ const index = ev.target.index as number | undefined;
+ // undefined = remove
+ const newValue = ev.detail.value as string | undefined;
+
+ let updatedValue: string[] | undefined;
+
+ if (index === undefined) {
+ if (newValue) {
+ updatedValue = [...this._normalizedValue, newValue];
+ }
+ ev.target.value = "";
+ } else if (newValue) {
+ updatedValue = [...this._normalizedValue];
+ updatedValue[index] = newValue;
+ } else {
+ updatedValue = this._normalizedValue.filter((_, i) => i !== index);
+ }
+
+ if (updatedValue) {
+ fireEvent(this, "value-changed", {
+ value: updatedValue,
+ });
+ }
+ }
+
+ static styles = css`
+ ha-entity-picker + ha-entity-picker {
+ display: block;
+ margin-top: 16px;
+ }
+ `;
}
declare global {
diff --git a/src/data/selector.ts b/src/data/selector.ts
index c8cc87b36e..76f673b125 100644
--- a/src/data/selector.ts
+++ b/src/data/selector.ts
@@ -23,6 +23,7 @@ export interface EntitySelector {
integration?: string;
domain?: string | string[];
device_class?: string;
+ multiple?: boolean;
};
}