From fa578b9673fa0b31db6a3187b5575fcbf3738c6f Mon Sep 17 00:00:00 2001 From: mertsincan Date: Sun, 5 Dec 2021 20:18:38 +0300 Subject: [PATCH] Fixed #1843 - Add virtualScroller feature to DataTable --- src/components/column/Column.d.ts | 63 +++++++++++++++ src/components/datatable/BodyCell.vue | 27 ++++++- src/components/datatable/DataTable.vue | 104 +++++++++++++++---------- src/components/datatable/TableBody.vue | 67 ++++++++++++---- 4 files changed, 205 insertions(+), 56 deletions(-) diff --git a/src/components/column/Column.d.ts b/src/components/column/Column.d.ts index 7132757bc..0c75d6668 100755 --- a/src/components/column/Column.d.ts +++ b/src/components/column/Column.d.ts @@ -1,5 +1,6 @@ import { VNode } from 'vue'; import { ClassComponent, GlobalComponentConstructor } from '../ts-helpers'; +import { VirtualScrollerLoaderOptions } from '../virtualscroller'; type ColumnFieldType = string | ((item: any) => string) | undefined; @@ -22,6 +23,37 @@ export interface ColumnFilterMatchModeOptions { [key: string]: string; } +export interface ColumnLoadingOptions extends VirtualScrollerLoaderOptions { + /** + * Cell index + */ + cellIndex: number; + /** + * Whether the cell is first. + */ + cellFirst: boolean; + /** + * Whether the cell is last. + */ + cellLast: boolean; + /** + * Whether the cell is even. + */ + cellEven: boolean; + /** + * Whether the item is odd. + */ + cellOdd: boolean; + /** + * Column instance + */ + column: Column; + /** + * Column field + */ + field: string; +} + export interface ColumnProps { /** * Identifier of a column if field property is not defined. @@ -375,6 +407,37 @@ export interface ColumnSlots { */ filterCallback: () => void; }) => VNode[]; + /** + * Custom loading template. + * @param {Object} scope - loading slot's params. + */ + loading: (scope: { + /** + * Row data. + */ + data: any; + /** + * Column node. + */ + column: Column; + /** + * Column field. + */ + field: string; + /** + * Row index. + */ + index: number; + /** + * Whether the row is frozen. + */ + frozenRow: boolean; + /** + * Loading options. + * @see ColumnLoadingOptions + */ + loadingOptions: ColumnLoadingOptions; + }) => VNode[]; } export declare type ColumnEmits = { diff --git a/src/components/datatable/BodyCell.vue b/src/components/datatable/BodyCell.vue index 83304cee2..b0e5b0788 100755 --- a/src/components/datatable/BodyCell.vue +++ b/src/components/datatable/BodyCell.vue @@ -1,5 +1,8 @@ -
- - - - - -
+
+ + +
@@ -69,6 +74,7 @@ import {ObjectUtils,DomHandler,UniqueComponentId} from 'primevue/utils'; import {FilterMatchMode,FilterOperator,FilterService} from 'primevue/api'; import Paginator from 'primevue/paginator'; +import VirtualScroller from 'primevue/virtualscroller'; import TableHeader from './TableHeader.vue'; import TableBody from './TableBody.vue'; import TableFooter from './TableFooter.vue'; @@ -297,6 +303,10 @@ export default { type: String, default: "vertical" }, + virtualScrollerOptions: { + type: Object, + default: null + }, scrollHeight: { type: String, default: null @@ -1766,6 +1776,16 @@ export default { } return results; }, + dataToRender(data) { + const _data = data || this.processedData; + + if (_data && this.paginator) { + const first = this.lazy ? 0 : this.d_first; + return _data.slice(first, first + this.d_rows); + } + + return _data; + } }, computed: { containerClass() { @@ -1859,17 +1879,6 @@ export default { return data; }, - dataToRender() { - const data = this.processedData; - - if (data && this.paginator) { - const first = this.lazy ? 0 : this.d_first; - return data.slice(first, first + this.d_rows); - } - else { - return data; - } - }, totalRecordsLength() { if (this.lazy) { return this.totalRecords; @@ -1905,6 +1914,9 @@ export default { }, groupRowSortField() { return this.sortMode === 'single' ? this.sortField : (this.d_groupRowsSortMeta ? this.d_groupRowsSortMeta.field : null); + }, + virtualScrollerDisabled() { + return ObjectUtils.isEmpty(this.virtualScrollerOptions) || !this.scrollable; } }, components: { @@ -1912,6 +1924,7 @@ export default { 'DTTableHeader': TableHeader, 'DTTableBody': TableBody, 'DTTableFooter': TableFooter, + 'DTVirtualScroller': VirtualScroller } } @@ -2205,4 +2218,13 @@ export default { .p-datatable .p-datatable-tbody > tr > td > .p-column-title { display: none; } + +/* VirtualScroller */ +.p-datatable .p-virtualscroller-loading { + transform: none !important; + min-height: 0; + position: sticky; + top: 0; + left: 0; +} diff --git a/src/components/datatable/TableBody.vue b/src/components/datatable/TableBody.vue index 3d61293e3..e389d5bdb 100755 --- a/src/components/datatable/TableBody.vue +++ b/src/components/datatable/TableBody.vue @@ -1,37 +1,37 @@