diff --git a/src/common/decorators/restore-scroll.ts b/src/common/decorators/restore-scroll.ts new file mode 100644 index 0000000000..29535d07e0 --- /dev/null +++ b/src/common/decorators/restore-scroll.ts @@ -0,0 +1,33 @@ +import type { LitElement } from "lit-element"; +import type { ClassElement } from "../../types"; + +export const restoreScroll = (selector: string): any => { + return (element: ClassElement) => ({ + kind: "method", + placement: "prototype", + key: element.key, + descriptor: { + set(this: LitElement, value: number) { + this[`__${String(element.key)}`] = value; + }, + get(this: LitElement) { + return this[`__${String(element.key)}`]; + }, + enumerable: true, + configurable: true, + }, + finisher(cls: typeof LitElement) { + const connectedCallback = cls.prototype.connectedCallback; + cls.prototype.connectedCallback = function () { + connectedCallback.call(this); + if (this[element.key]) { + const target = this.renderRoot.querySelector(selector); + if (!target) { + return; + } + target.scrollTop = this[element.key]; + } + }; + }, + }); +}; diff --git a/src/components/data-table/ha-data-table.ts b/src/components/data-table/ha-data-table.ts index c1150236ca..a3194ad23d 100644 --- a/src/components/data-table/ha-data-table.ts +++ b/src/components/data-table/ha-data-table.ts @@ -9,6 +9,8 @@ import { PropertyValues, query, TemplateResult, + eventOptions, + internalProperty, } from "lit-element"; import { classMap } from "lit-html/directives/class-map"; import { ifDefined } from "lit-html/directives/if-defined"; @@ -23,6 +25,7 @@ import type { HaCheckbox } from "../ha-checkbox"; import "../ha-icon"; import { filterData, sortData } from "./sort-filter"; import memoizeOne from "memoize-one"; +import { restoreScroll } from "../../common/decorators/restore-scroll"; declare global { // for fire event @@ -96,15 +99,15 @@ export class HaDataTable extends LitElement { @property({ type: String }) public filter = ""; - @property({ type: Boolean }) private _filterable = false; + @internalProperty() private _filterable = false; - @property({ type: String }) private _filter = ""; + @internalProperty() private _filter = ""; - @property({ type: String }) private _sortColumn?: string; + @internalProperty() private _sortColumn?: string; - @property({ type: String }) private _sortDirection: SortingDirection = null; + @internalProperty() private _sortDirection: SortingDirection = null; - @property({ type: Array }) private _filteredData: DataTableRowData[] = []; + @internalProperty() private _filteredData: DataTableRowData[] = []; @query("slot[name='header']") private _header!: HTMLSlotElement; @@ -118,6 +121,9 @@ export class HaDataTable extends LitElement { private curRequest = 0; + // @ts-ignore + @restoreScroll(".scroller") private _savedScrollPos?: number; + private _debounceSearch = debounce( (value: string) => { this._filter = value; @@ -286,7 +292,10 @@ export class HaDataTable extends LitElement { ` : html` -