diff --git a/src/components/device/ha-device-picker.ts b/src/components/device/ha-device-picker.ts index 3e17e093c7..cd7dfe7688 100644 --- a/src/components/device/ha-device-picker.ts +++ b/src/components/device/ha-device-picker.ts @@ -14,6 +14,8 @@ import { property, } from "lit-element"; import { UnsubscribeFunc } from "home-assistant-js-websocket"; +import { SubscribeMixin } from "../../../src/mixins/subscribe-mixin"; + import { HomeAssistant } from "../../types"; import { fireEvent } from "../../common/dom/fire_event"; import { @@ -23,12 +25,11 @@ import { import { compare } from "../../common/string/compare"; @customElement("ha-device-picker") -class HaDevicePicker extends LitElement { +class HaDevicePicker extends SubscribeMixin(LitElement) { @property() public hass?: HomeAssistant; @property() public label?: string; @property() public value?: string; @property() public devices?: DeviceRegistryEntry[]; - private _unsubDevices?: UnsubscribeFunc; private _sortedDevices = memoizeOne((devices?: DeviceRegistryEntry[]) => { if (!devices || devices.length === 1) { @@ -39,22 +40,12 @@ class HaDevicePicker extends LitElement { return sorted; }); - public connectedCallback() { - super.connectedCallback(); - this._unsubDevices = subscribeDeviceRegistry( - this.hass!.connection!, - (devices) => { + public hassSubscribe(): UnsubscribeFunc[] { + return [ + subscribeDeviceRegistry(this.hass!.connection!, (devices) => { this.devices = devices; - } - ); - } - - public disconnectedCallback() { - super.disconnectedCallback(); - if (this._unsubDevices) { - this._unsubDevices(); - this._unsubDevices = undefined; - } + }), + ]; } protected render(): TemplateResult | void { diff --git a/src/mixins/subscribe-mixin.ts b/src/mixins/subscribe-mixin.ts new file mode 100644 index 0000000000..25cca233b5 --- /dev/null +++ b/src/mixins/subscribe-mixin.ts @@ -0,0 +1,65 @@ +import { + LitElement, + Constructor, + PropertyValues, + PropertyDeclarations, +} from "lit-element"; +import { UnsubscribeFunc } from "home-assistant-js-websocket"; + +export interface HassSubscribeElement { + hassSubscribe(): UnsubscribeFunc[]; +} + +/* tslint:disable-next-line */ +export const SubscribeMixin = ( + superClass: Constructor +): Constructor => + // @ts-ignore + class extends superClass { + /* tslint:disable-next-line */ + private __unsubs?: UnsubscribeFunc[]; + + static get properties(): PropertyDeclarations { + return { + hass: {}, + }; + } + + public connectedCallback() { + super.connectedCallback(); + this.__checkSubscribed(); + } + + public disconnectedCallback() { + super.disconnectedCallback(); + if (this.__unsubs) { + while (this.__unsubs.length) { + this.__unsubs.pop()!(); + } + this.__unsubs = undefined; + } + } + + protected updated(changedProps: PropertyValues) { + super.updated(changedProps); + if (changedProps.has("hass")) { + this.__checkSubscribed(); + } + } + + protected hassSubscribe(): UnsubscribeFunc[] { + super.hassSubscribe(); + return []; + } + + private __checkSubscribed(): void { + if ( + this.__unsubs !== undefined || + !((this as unknown) as Element).isConnected || + super.hass === undefined + ) { + return; + } + this.__unsubs = this.hassSubscribe(); + } + };