diff --git a/src/components/data-table/ha-data-table.ts b/src/components/data-table/ha-data-table.ts index 60faa4dcaf..77550488c9 100644 --- a/src/components/data-table/ha-data-table.ts +++ b/src/components/data-table/ha-data-table.ts @@ -25,7 +25,6 @@ import { fireEvent } from "../../common/dom/fire_event"; import { stringCompare } from "../../common/string/compare"; import { debounce } from "../../common/util/debounce"; import { groupBy } from "../../common/util/group-by"; -import { nextRender } from "../../common/util/render-status"; import { haStyleScrollbar } from "../../resources/styles"; import { loadVirtualizer } from "../../resources/virtualizer"; import { HomeAssistant } from "../../types"; @@ -35,6 +34,7 @@ import "../ha-svg-icon"; import "../search-input"; import { filterData, sortData } from "./sort-filter"; import { LocalizeFunc } from "../../common/translations/localize"; +import { nextRender } from "../../common/util/render-status"; export interface RowClickedEvent { id: string; @@ -169,8 +169,6 @@ export class HaDataTable extends LitElement { @query("slot[name='header']") private _header!: HTMLSlotElement; - @state() private _items: DataTableRowData[] = []; - @state() private _collapsedGroups: string[] = []; private _checkableRowsCount?: number; @@ -179,7 +177,9 @@ export class HaDataTable extends LitElement { private _sortColumns: SortableColumnContainer = {}; - private curRequest = 0; + private _curRequest = 0; + + private _lastUpdate = 0; // @ts-ignore @restoreScroll(".scroller") private _savedScrollPos?: number; @@ -206,9 +206,9 @@ export class HaDataTable extends LitElement { public connectedCallback() { super.connectedCallback(); - if (this._items.length) { + if (this._filteredData.length) { // Force update of location of rows - this._items = [...this._items]; + this._filteredData = [...this._filteredData]; } } @@ -291,16 +291,13 @@ export class HaDataTable extends LitElement { properties.has("columns") || properties.has("_filter") || properties.has("sortColumn") || - properties.has("sortDirection") || - properties.has("groupColumn") || - properties.has("groupOrder") || - properties.has("_collapsedGroups") + properties.has("sortDirection") ) { this._sortFilterData(); } if (properties.has("selectable") || properties.has("hiddenColumns")) { - this._items = [...this._items]; + this._filteredData = [...this._filteredData]; } } @@ -467,7 +464,15 @@ export class HaDataTable extends LitElement { scroller class="mdc-data-table__content scroller ha-scrollbar" @scroll=${this._saveScrollPos} - .items=${this._items} + .items=${this._groupData( + this._filteredData, + localize, + this.appendRow, + this.hasFab, + this.groupColumn, + this.groupOrder, + this._collapsedGroups + )} .keyFunction=${this._keyFunction} .renderItem=${renderRow} > @@ -602,8 +607,13 @@ export class HaDataTable extends LitElement { private async _sortFilterData() { const startTime = new Date().getTime(); - this.curRequest++; - const curRequest = this.curRequest; + const timeBetweenUpdate = startTime - this._lastUpdate; + const timeBetweenRequest = startTime - this._curRequest; + this._curRequest = startTime; + + const forceUpdate = + !this._lastUpdate || + (timeBetweenUpdate > 500 && timeBetweenRequest < 500); let filteredData = this.data; if (this._filter) { @@ -614,6 +624,10 @@ export class HaDataTable extends LitElement { ); } + if (!forceUpdate && this._curRequest !== startTime) { + return; + } + const prom = this.sortColumn ? sortData( filteredData, @@ -634,91 +648,103 @@ export class HaDataTable extends LitElement { setTimeout(resolve, 100 - elapsed); }); } - if (this.curRequest !== curRequest) { + + if (!forceUpdate && this._curRequest !== startTime) { return; } - const localize = this.localizeFunc || this.hass.localize; - - if (this.appendRow || this.hasFab || this.groupColumn) { - let items = [...data]; - - if (this.groupColumn) { - const grouped = groupBy(items, (item) => item[this.groupColumn!]); - if (grouped.undefined) { - // make sure ungrouped items are at the bottom - grouped[UNDEFINED_GROUP_KEY] = grouped.undefined; - delete grouped.undefined; - } - const sorted: { - [key: string]: DataTableRowData[]; - } = Object.keys(grouped) - .sort((a, b) => { - const orderA = this.groupOrder?.indexOf(a) ?? -1; - const orderB = this.groupOrder?.indexOf(b) ?? -1; - if (orderA !== orderB) { - if (orderA === -1) { - return 1; - } - if (orderB === -1) { - return -1; - } - return orderA - orderB; - } - return stringCompare( - ["", "-", "—"].includes(a) ? "zzz" : a, - ["", "-", "—"].includes(b) ? "zzz" : b, - this.hass.locale.language - ); - }) - .reduce((obj, key) => { - obj[key] = grouped[key]; - return obj; - }, {}); - const groupedItems: DataTableRowData[] = []; - Object.entries(sorted).forEach(([groupName, rows]) => { - groupedItems.push({ - append: true, - content: html`