mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-25 18:26:35 +00:00
Allow selecting multiple entities (#11986)
This commit is contained in:
parent
68e7ce1883
commit
fc6b594a27
@ -175,6 +175,12 @@ const SCHEMAS: {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "Multiples",
|
||||||
|
input: {
|
||||||
|
entity: { name: "Entity", selector: { entity: { multiple: true } } },
|
||||||
|
},
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@customElement("demo-components-ha-selector")
|
@customElement("demo-components-ha-selector")
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import { HassEntity, UnsubscribeFunc } from "home-assistant-js-websocket";
|
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 { 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 { computeStateDomain } from "../../common/entity/compute_state_domain";
|
||||||
import { subscribeEntityRegistry } from "../../data/entity_registry";
|
import { subscribeEntityRegistry } from "../../data/entity_registry";
|
||||||
import { EntitySelector } from "../../data/selector";
|
import { EntitySelector } from "../../data/selector";
|
||||||
@ -23,14 +25,45 @@ export class HaEntitySelector extends SubscribeMixin(LitElement) {
|
|||||||
@property({ type: Boolean }) public disabled = false;
|
@property({ type: Boolean }) public disabled = false;
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
return html`<ha-entity-picker
|
if (!this.selector.entity.multiple) {
|
||||||
.hass=${this.hass}
|
return html`<ha-entity-picker
|
||||||
.value=${this.value}
|
.hass=${this.hass}
|
||||||
.label=${this.label}
|
.value=${this.value}
|
||||||
.entityFilter=${this._filterEntities}
|
.label=${this.label}
|
||||||
.disabled=${this.disabled}
|
.entityFilter=${this._filterEntities}
|
||||||
allow-custom-entity
|
.disabled=${this.disabled}
|
||||||
></ha-entity-picker>`;
|
allow-custom-entity
|
||||||
|
></ha-entity-picker>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For multiple, the value is a list.
|
||||||
|
const value = this._normalizedValue as string[];
|
||||||
|
|
||||||
|
return html`
|
||||||
|
${this.label ? html`<div>${this.label}</div>` : ""}
|
||||||
|
${repeat(
|
||||||
|
value,
|
||||||
|
(val) => val,
|
||||||
|
(entityId, index) => html`
|
||||||
|
<ha-entity-picker
|
||||||
|
.hass=${this.hass}
|
||||||
|
.value=${entityId}
|
||||||
|
.entityFilter=${this._filterEntities}
|
||||||
|
.disabled=${this.disabled}
|
||||||
|
.index=${index}
|
||||||
|
allow-custom-entity
|
||||||
|
@value-changed=${this._valueChanged}
|
||||||
|
></ha-entity-picker>
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
<ha-entity-picker
|
||||||
|
.hass=${this.hass}
|
||||||
|
.entityFilter=${this._filterEntities}
|
||||||
|
.disabled=${this.disabled}
|
||||||
|
allow-custom-entity
|
||||||
|
@value-changed=${this._valueChanged}
|
||||||
|
></ha-entity-picker>
|
||||||
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
public hassSubscribe(): UnsubscribeFunc[] {
|
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 => {
|
private _filterEntities = (entity: HassEntity): boolean => {
|
||||||
if (this.selector.entity?.domain) {
|
if (this.selector.entity?.domain) {
|
||||||
const filterDomain = this.selector.entity.domain;
|
const filterDomain = this.selector.entity.domain;
|
||||||
@ -79,6 +123,43 @@ export class HaEntitySelector extends SubscribeMixin(LitElement) {
|
|||||||
}
|
}
|
||||||
return true;
|
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 {
|
declare global {
|
||||||
|
@ -23,6 +23,7 @@ export interface EntitySelector {
|
|||||||
integration?: string;
|
integration?: string;
|
||||||
domain?: string | string[];
|
domain?: string | string[];
|
||||||
device_class?: string;
|
device_class?: string;
|
||||||
|
multiple?: boolean;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user