From 360ad46404c1f6b710f7bdd9cf531341eb263ae7 Mon Sep 17 00:00:00 2001 From: cagataycivici Date: Tue, 22 Oct 2019 10:36:04 +0300 Subject: [PATCH] Implemented TableState --- src/components/datatable/DataTable.vue | 199 +++++++++++++- src/router.js | 7 +- src/views/datatable/DataTableStateDemo.vue | 303 +++++++++++++++++++++ src/views/datatable/DataTableSubMenu.vue | 1 + 4 files changed, 504 insertions(+), 6 deletions(-) create mode 100644 src/views/datatable/DataTableStateDemo.vue diff --git a/src/components/datatable/DataTable.vue b/src/components/datatable/DataTable.vue index 0d2f41a6b..118f1fe90 100644 --- a/src/components/datatable/DataTable.vue +++ b/src/components/datatable/DataTable.vue @@ -295,6 +295,14 @@ export default { expandedRowGroups: { type: Array, default: null + }, + stateStorage: { + type: String, + default: 'session' + }, + stateKey: { + type: String, + default: null } }, data() { @@ -307,7 +315,7 @@ export default { d_multiSortMeta: this.multiSortMeta ? [...this.multiSortMeta] : [], d_selectionKeys: null, d_expandedRowKeys: null, - columnOrder: null + d_columnOrder: null }; }, rowTouched: false, @@ -324,6 +332,9 @@ export default { draggedRowIndex: null, droppedRowIndex: null, rowDragging: null, + columnWidthsState: null, + tableWidthState: null, + columnWidthsRestored: false, watch: { first(newValue) { this.d_first = newValue; @@ -351,6 +362,11 @@ export default { } } }, + beforeMount() { + if (this.isStateful()) { + this.restoreState(); + } + }, mounted() { this.allChildren = this.$children; @@ -361,12 +377,22 @@ export default { columnOrder.push(child.columnKey||child.field); } } - this.columnOrder = columnOrder; + this.d_columnOrder = columnOrder; } }, beforeDestroy() { this.unbindColumnResizeEvents(); }, + updated() { + if (this.isStateful()) { + this.saveState(); + + if (this.resizableColumns && !this.columnWidthsRestored) { + this.restoreColumnWidths(); + this.columnWidthsRestored = true; + } + } + }, methods: { resolveFieldData(rowData, field) { return ObjectUtils.resolveFieldData(rowData, field); @@ -1015,6 +1041,10 @@ export default { DomHandler.removeClass(this.$el, 'p-unselectable-text'); this.unbindColumnResizeEvents(); + + if (this.isStateful()) { + this.saveState(); + } }, bindColumnResizeEvents() { if (!this.documentColumnResizeListener) { @@ -1114,7 +1144,7 @@ export default { } if (allowDrop) { - ObjectUtils.reorderArray(this.columnOrder, dragIndex, dropIndex); + ObjectUtils.reorderArray(this.d_columnOrder, dragIndex, dropIndex); this.$emit('column-reorder', { originalEvent: event, @@ -1368,6 +1398,165 @@ export default { else { return null; } + }, + isStateful() { + return this.stateKey != null; + }, + getStorage() { + switch(this.stateStorage) { + case 'local': + return window.localStorage; + + case 'session': + return window.sessionStorage; + + default: + throw new Error(this.stateStorage + ' is not a valid value for the state storage, supported values are "local" and "session".'); + } + }, + saveState() { + const storage = this.getStorage(); + let state = {}; + + if (this.paginator) { + state.first = this.d_first; + state.rows = this.d_rows; + } + + if (this.d_sortField) { + state.sortField = this.d_sortField; + state.sortOrder = this.d_sortOrder; + } + + if (this.d_multiSortMeta) { + state.multiSortMeta = this.d_multiSortMeta; + } + + if (this.hasFilters) { + state.filters = this.filters; + } + + if (this.resizableColumns) { + this.saveColumnWidths(state); + } + + if (this.reorderableColumns) { + state.columnOrder = this.d_columnOrder; + } + + if (this.expandedRows) { + state.expandedRows = this.expandedRows; + state.expandedRowKeys = this.d_expandedRowKeys; + } + + if (this.expandedRowGroups) { + state.expandedRowGroups = this.expandedRowGroups; + } + + if (this.selection) { + state.selection = this.selection; + state.selectionKeys = this.d_selectionKeys; + } + + if (Object.keys(state).length) { + storage.setItem(this.stateKey, JSON.stringify(state)); + } + }, + restoreState() { + const storage = this.getStorage(); + const stateString = storage.getItem(this.stateKey); + + if (stateString) { + let restoredState = JSON.parse(stateString); + + if (this.paginator) { + this.d_first = restoredState.first; + this.d_rows = restoredState.rows; + } + + if (restoredState.sortField) { + this.d_sortField = restoredState.sortField; + this.d_sortOrder = restoredState.sortOrder; + } + + if (restoredState.multiSortMeta) { + this.d_multiSortMeta = restoredState.multiSortMeta; + } + + if (restoredState.filters) { + this.$emit('update:filters', restoredState.filters); + } + + if (this.resizableColumns) { + this.columnWidthsState = restoredState.columnWidths; + this.tableWidthState = restoredState.tableWidth; + } + + if (this.reorderableColumns) { + this.d_columnOrder = restoredState.columnOrder; + } + + if (restoredState.expandedRows) { + this.d_expandedRowKeys = restoredState.expandedRowKeys; + this.$emit('update:expandedRows', restoredState.expandedRows); + } + + if (restoredState.expandedRowGroups) { + this.$emit('update:expandedRowGroups', restoredState.expandedRowGroups); + } + + if (this.selection) { + this.selection = restoredState.selection; + this.d_selectionKeys = restoredState.d_selectionKeys; + this.$emit('update:selection', this.selection); + } + } + }, + saveColumnWidths(state) { + let widths = []; + let headers = DomHandler.find(this.$el, '.p-datatable-thead > tr > th'); + headers.forEach(header => widths.push(DomHandler.getOuterWidth(header))); + state.columnWidths = widths.join(','); + + if (this.columnResizeMode === 'expand') { + /*TODO: Keep state when scrollable tables are implemented + state.tableWidth = this.scrollable ? DomHandler.findSingle(this.container, '.p-datatable-scrollable-header-table').style.width : + DomHandler.getOuterWidth(this.table) + 'px';*/ + state.tableWidth = DomHandler.getOuterWidth(this.$refs.table) + 'px' + } + }, + restoreColumnWidths() { + //TODO: Restore state when scrollable tables are implemented + if (this.columnWidthsState) { + let widths = this.columnWidthsState.split(','); + + if (this.columnResizeMode === 'expand' && this.tableWidthState) { + this.$refs.table.style.width = this.tableWidthState; + this.$el.style.width = this.tableWidthState; + + /*if (this.scrollable) { + this.setScrollableItemsWidthOnExpandResize(null, this.tableWidthState, 0); + } + else { + this.$refs.table.style.width = this.tableWidthState; + this.$el.style.width = this.tableWidthState; + }*/ + } + /* + if (this.props.scrollable) { + let headerCols = DomHandler.find(this.container, '.p-datatable-scrollable-header-table > colgroup > col'); + let bodyCols = DomHandler.find(this.container, '.p-datatable-scrollable-body-table > colgroup > col'); + + headerCols.map((col, index) => col.style.width = widths[index] + 'px'); + bodyCols.map((col, index) => col.style.width = widths[index] + 'px'); + } + else { + let headers = DomHandler.find(this.table, '.p-datatable-thead > tr > th'); + headers.map((header, index) => header.style.width = widths[index] + 'px'); + }*/ + let headers = DomHandler.find(this.$refs.table, '.p-datatable-thead > tr > th'); + headers.forEach((header, index) => header.style.width = widths[index] + 'px'); + } } }, computed: { @@ -1387,9 +1576,9 @@ export default { if (this.allChildren) { columns = this.allChildren.filter(child => child.$options._propKeys.indexOf('columnKey') !== -1); - if (this.reorderableColumns && this.columnOrder) { + if (this.reorderableColumns && this.d_columnOrder) { let orderedColumns = []; - for (let columnKey of this.columnOrder) { + for (let columnKey of this.d_columnOrder) { let column = this.findColumnByKey(columns, columnKey); if (column) { orderedColumns.push(column); diff --git a/src/router.js b/src/router.js index 5ab29a30a..cb6de7829 100644 --- a/src/router.js +++ b/src/router.js @@ -185,7 +185,12 @@ export default new Router({ path: '/datatable/rowexpand', name: 'datatablerowexpand', component: () => import('./views/datatable/DataTableRowExpandDemo.vue') - }, + }, + { + path: '/datatable/state', + name: 'datatablestate', + component: () => import('./views/datatable/DataTableStateDemo.vue') + }, { path: '/datatable/crud', name: 'datatablecrud', diff --git a/src/views/datatable/DataTableStateDemo.vue b/src/views/datatable/DataTableStateDemo.vue new file mode 100644 index 000000000..ee415a826 --- /dev/null +++ b/src/views/datatable/DataTableStateDemo.vue @@ -0,0 +1,303 @@ + + + + + \ No newline at end of file diff --git a/src/views/datatable/DataTableSubMenu.vue b/src/views/datatable/DataTableSubMenu.vue index cd56a20d9..0db71eb3d 100644 --- a/src/views/datatable/DataTableSubMenu.vue +++ b/src/views/datatable/DataTableSubMenu.vue @@ -16,6 +16,7 @@
  • ● RowGroup
  • ● Responsive
  • ● Export
  • +
  • ● State
  • ● Crud