primevue-mirror/components/lib/treetable/TreeTable.vue

842 lines
34 KiB
Vue
Raw Normal View History

2022-09-06 12:03:37 +00:00
<template>
2023-06-05 07:34:19 +00:00
<div :class="cx('root')" data-scrollselectors=".p-treetable-scrollable-body" role="table" v-bind="ptm('root')" data-pc-name="treetable">
<div v-if="loading" :class="cx('loadingWrapper')" v-bind="ptm('loadingWrapper')">
<div :class="cx('loadingOverlay')" v-bind="ptm('loadingOverlay')">
<slot name="loadingicon" :class="cx('loadingIcon')">
<component :is="loadingIcon ? 'span' : 'SpinnerIcon'" spin :class="[cx('loadingIcon'), loadingIcon]" v-bind="ptm('loadingIcon')" />
</slot>
2022-09-06 12:03:37 +00:00
</div>
</div>
2023-06-05 07:34:19 +00:00
<div v-if="$slots.header" :class="cx('header')" v-bind="ptm('header')">
2022-09-06 12:03:37 +00:00
<slot name="header"></slot>
</div>
2022-09-14 11:26:01 +00:00
<TTPaginator
v-if="paginatorTop"
:rows="d_rows"
:first="d_first"
:totalRecords="totalRecordsLength"
:pageLinkSize="pageLinkSize"
:template="paginatorTemplate"
:rowsPerPageOptions="rowsPerPageOptions"
:currentPageReportTemplate="currentPageReportTemplate"
2023-06-05 07:34:19 +00:00
:class="cx('paginator')"
2022-09-14 11:26:01 +00:00
@page="onPage($event)"
:alwaysShow="alwaysShowPaginator"
2023-05-11 08:11:49 +00:00
:pt="ptm('paginator')"
2023-06-05 07:34:19 +00:00
data-pc-section="paginator"
2022-09-14 11:26:01 +00:00
>
<template v-if="$slots.paginatorstart" #start>
2022-09-06 12:03:37 +00:00
<slot name="paginatorstart"></slot>
</template>
2022-09-14 11:26:01 +00:00
<template v-if="$slots.paginatorend" #end>
2022-09-06 12:03:37 +00:00
<slot name="paginatorend"></slot>
</template>
<template v-if="$slots.paginatorfirstpagelinkicon" #firstpagelinkicon>
<slot name="paginatorfirstpagelinkicon"></slot>
</template>
<template v-if="$slots.paginatorprevpagelinkicon" #prevpagelinkicon>
<slot name="paginatorprevpagelinkicon"></slot>
</template>
<template v-if="$slots.paginatornextpagelinkicon" #nextpagelinkicon>
<slot name="paginatornextpagelinkicon"></slot>
</template>
<template v-if="$slots.paginatorlastpagelinkicon" #lastpagelinkicon>
<slot name="paginatorlastpagelinkicon"></slot>
</template>
2022-09-06 12:03:37 +00:00
</TTPaginator>
2023-06-05 07:34:19 +00:00
<div :class="cx('wrapper')" :style="{ maxHeight: scrollHeight }" v-bind="ptm('wrapper')">
2023-05-11 08:11:49 +00:00
<table ref="table" role="table" v-bind="{ ...tableProps, ...ptm('table') }">
2023-06-05 07:34:19 +00:00
<thead :class="cx('thead')" role="rowgroup" v-bind="ptm('thead')">
2023-05-11 08:11:49 +00:00
<tr role="row" v-bind="ptm('headerRow')">
2022-09-14 11:26:01 +00:00
<template v-for="(col, i) of columns" :key="columnProp(col, 'columnKey') || columnProp(col, 'field') || i">
<TTHeaderCell
v-if="!columnProp(col, 'hidden')"
:column="col"
:resizableColumns="resizableColumns"
:sortField="d_sortField"
:sortOrder="d_sortOrder"
:multiSortMeta="d_multiSortMeta"
:sortMode="sortMode"
@column-click="onColumnHeaderClick"
@column-resizestart="onColumnResizeStart"
2023-05-11 08:11:49 +00:00
:pt="pt"
2022-09-14 11:26:01 +00:00
></TTHeaderCell>
2022-09-06 12:03:37 +00:00
</template>
</tr>
2023-05-11 08:11:49 +00:00
<tr v-if="hasColumnFilter()" v-bind="ptm('headerRow')">
2022-09-14 11:26:01 +00:00
<template v-for="(col, i) of columns" :key="columnProp(col, 'columnKey') || columnProp(col, 'field') || i">
2023-05-11 08:11:49 +00:00
<th v-if="!columnProp(col, 'hidden')" :class="getFilterColumnHeaderClass(col)" :style="[columnProp(col, 'style'), columnProp(col, 'filterHeaderStyle')]" v-bind="ptm('headerCell')">
2022-09-14 11:26:01 +00:00
<component v-if="col.children && col.children.filter" :is="col.children.filter" :column="col" />
2022-09-06 12:03:37 +00:00
</th>
</template>
</tr>
</thead>
2023-06-05 07:34:19 +00:00
<tbody :class="cx('tbody')" role="rowgroup" v-bind="ptm('tbody')">
2022-09-06 12:03:37 +00:00
<template v-if="!empty">
2022-09-14 11:26:01 +00:00
<TTRow
2022-12-08 11:04:25 +00:00
v-for="(node, index) of dataToRender"
2022-09-14 11:26:01 +00:00
:key="node.key"
:columns="columns"
:node="node"
:level="0"
:expandedKeys="d_expandedKeys"
:indentation="indentation"
:selectionMode="selectionMode"
:selectionKeys="selectionKeys"
2022-12-08 11:04:25 +00:00
:ariaSetSize="dataToRender.length"
:ariaPosInset="index + 1"
:tabindex="setTabindex(node, index)"
:templates="$slots"
2022-12-08 11:04:25 +00:00
@node-toggle="onNodeToggle"
2022-09-14 11:26:01 +00:00
@node-click="onNodeClick"
@checkbox-change="onCheckboxChange"
2023-05-11 08:11:49 +00:00
:pt="pt"
2022-09-14 11:26:01 +00:00
></TTRow>
2022-09-06 12:03:37 +00:00
</template>
2023-06-05 07:34:19 +00:00
<tr v-else :class="cx('emptyMessage')" v-bind="ptm('emptyMessage')">
2023-05-11 08:11:49 +00:00
<td :colspan="columns.length" v-bind="ptm('bodyCell')">
2022-09-06 12:03:37 +00:00
<slot name="empty"></slot>
</td>
</tr>
</tbody>
2023-06-05 07:34:19 +00:00
<tfoot v-if="hasFooter" :class="cx('tfoot')" role="rowgroup" v-bind="ptm('tfoot')">
2023-05-11 08:11:49 +00:00
<tr role="row" v-bind="ptm('footerRow')">
2022-09-14 11:26:01 +00:00
<template v-for="(col, i) of columns" :key="columnProp(col, 'columnKey') || columnProp(col, 'field') || i">
2023-05-11 08:11:49 +00:00
<TTFooterCell v-if="!columnProp(col, 'hidden')" :column="col" :pt="pt"></TTFooterCell>
2022-09-06 12:03:37 +00:00
</template>
</tr>
</tfoot>
</table>
</div>
2022-09-14 11:26:01 +00:00
<TTPaginator
v-if="paginatorBottom"
:rows="d_rows"
:first="d_first"
:totalRecords="totalRecordsLength"
:pageLinkSize="pageLinkSize"
:template="paginatorTemplate"
:rowsPerPageOptions="rowsPerPageOptions"
:currentPageReportTemplate="currentPageReportTemplate"
2023-06-05 07:34:19 +00:00
:class="cx('paginator')"
2022-09-14 11:26:01 +00:00
@page="onPage($event)"
:alwaysShow="alwaysShowPaginator"
2023-05-11 08:11:49 +00:00
:pt="pt"
2023-06-05 07:34:19 +00:00
data-pc-section="paginator"
2022-09-14 11:26:01 +00:00
>
<template v-if="$slots.paginatorstart" #start>
2022-09-06 12:03:37 +00:00
<slot name="paginatorstart"></slot>
</template>
2022-09-14 11:26:01 +00:00
<template v-if="$slots.paginatorend" #end>
2022-09-06 12:03:37 +00:00
<slot name="paginatorend"></slot>
</template>
<template v-if="$slots.paginatorfirstpagelinkicon" #firstpagelinkicon>
<slot name="paginatorfirstpagelinkicon"></slot>
</template>
<template v-if="$slots.paginatorprevpagelinkicon" #prevpagelinkicon>
<slot name="paginatorprevpagelinkicon"></slot>
</template>
<template v-if="$slots.paginatornextpagelinkicon" #nextpagelinkicon>
<slot name="paginatornextpagelinkicon"></slot>
</template>
<template v-if="$slots.paginatorlastpagelinkicon" #lastpagelinkicon>
<slot name="paginatorlastpagelinkicon"></slot>
</template>
2022-09-06 12:03:37 +00:00
</TTPaginator>
2023-06-05 07:34:19 +00:00
<div v-if="$slots.footer" :class="cx('footer')" v-bind="ptm('footer')">
2022-09-06 12:03:37 +00:00
<slot name="footer"></slot>
</div>
2023-06-05 07:34:19 +00:00
<div ref="resizeHelper" :class="cx('resizeHelper')" style="display: none" v-bind="ptm('resizeHelper')"></div>
2022-09-06 12:03:37 +00:00
</div>
</template>
<script>
2022-09-14 11:26:01 +00:00
import { FilterService } from 'primevue/api';
import SpinnerIcon from 'primevue/icons/spinner';
2022-09-06 12:03:37 +00:00
import Paginator from 'primevue/paginator';
2022-12-08 11:04:25 +00:00
import { DomHandler, ObjectUtils } from 'primevue/utils';
2023-06-05 07:34:19 +00:00
import BaseTreeTable from './BaseTreeTable.vue';
2022-12-08 11:04:25 +00:00
import FooterCell from './FooterCell.vue';
import HeaderCell from './HeaderCell.vue';
import TreeTableRow from './TreeTableRow.vue';
2022-09-06 12:03:37 +00:00
export default {
name: 'TreeTable',
2023-06-05 07:34:19 +00:00
extends: BaseTreeTable,
2022-09-14 11:26:01 +00:00
emits: [
'node-expand',
'node-collapse',
'update:expandedKeys',
'update:selectionKeys',
'node-select',
'node-unselect',
'update:first',
'update:rows',
'page',
'update:sortField',
'update:sortOrder',
'update:multiSortMeta',
'sort',
'filter',
'column-resize-end'
],
2022-09-06 12:03:37 +00:00
documentColumnResizeListener: null,
documentColumnResizeEndListener: null,
lastResizeHelperX: null,
resizeColumnElement: null,
data() {
return {
d_expandedKeys: this.expandedKeys || {},
d_first: this.first,
d_rows: this.rows,
d_sortField: this.sortField,
d_sortOrder: this.sortOrder,
2022-12-08 11:04:25 +00:00
d_multiSortMeta: this.multiSortMeta ? [...this.multiSortMeta] : [],
hasASelectedNode: false
2022-09-14 11:26:01 +00:00
};
2022-09-06 12:03:37 +00:00
},
watch: {
expandedKeys(newValue) {
this.d_expandedKeys = newValue;
},
first(newValue) {
this.d_first = newValue;
},
rows(newValue) {
this.d_rows = newValue;
},
sortField(newValue) {
this.d_sortField = newValue;
},
sortOrder(newValue) {
this.d_sortOrder = newValue;
},
multiSortMeta(newValue) {
this.d_multiSortMeta = newValue;
}
},
mounted() {
if (this.scrollable && this.scrollDirection !== 'vertical') {
this.updateScrollWidth();
}
},
updated() {
if (this.scrollable && this.scrollDirection !== 'vertical') {
this.updateScrollWidth();
}
},
methods: {
columnProp(col, prop) {
return ObjectUtils.getVNodeProp(col, prop);
},
onNodeToggle(node) {
const key = node.key;
if (this.d_expandedKeys[key]) {
delete this.d_expandedKeys[key];
this.$emit('node-collapse', node);
2022-09-14 11:26:01 +00:00
} else {
2022-09-06 12:03:37 +00:00
this.d_expandedKeys[key] = true;
this.$emit('node-expand', node);
}
2022-09-14 11:26:01 +00:00
this.d_expandedKeys = { ...this.d_expandedKeys };
2022-09-06 12:03:37 +00:00
this.$emit('update:expandedKeys', this.d_expandedKeys);
},
onNodeClick(event) {
if (this.rowSelectionMode && event.node.selectable !== false) {
const metaSelection = event.nodeTouched ? false : this.metaKeySelection;
const _selectionKeys = metaSelection ? this.handleSelectionWithMetaKey(event) : this.handleSelectionWithoutMetaKey(event);
this.$emit('update:selectionKeys', _selectionKeys);
}
},
handleSelectionWithMetaKey(event) {
const originalEvent = event.originalEvent;
const node = event.node;
2022-09-14 11:26:01 +00:00
const metaKey = originalEvent.metaKey || originalEvent.ctrlKey;
2022-09-06 12:03:37 +00:00
const selected = this.isNodeSelected(node);
let _selectionKeys;
if (selected && metaKey) {
if (this.isSingleSelectionMode()) {
_selectionKeys = {};
2022-09-14 11:26:01 +00:00
} else {
_selectionKeys = { ...this.selectionKeys };
2022-09-06 12:03:37 +00:00
delete _selectionKeys[node.key];
}
this.$emit('node-unselect', node);
2022-09-14 11:26:01 +00:00
} else {
2022-09-06 12:03:37 +00:00
if (this.isSingleSelectionMode()) {
_selectionKeys = {};
2022-09-14 11:26:01 +00:00
} else if (this.isMultipleSelectionMode()) {
_selectionKeys = !metaKey ? {} : this.selectionKeys ? { ...this.selectionKeys } : {};
2022-09-06 12:03:37 +00:00
}
_selectionKeys[node.key] = true;
this.$emit('node-select', node);
}
return _selectionKeys;
},
handleSelectionWithoutMetaKey(event) {
const node = event.node;
const selected = this.isNodeSelected(node);
let _selectionKeys;
if (this.isSingleSelectionMode()) {
if (selected) {
_selectionKeys = {};
this.$emit('node-unselect', node);
2022-09-14 11:26:01 +00:00
} else {
2022-09-06 12:03:37 +00:00
_selectionKeys = {};
_selectionKeys[node.key] = true;
this.$emit('node-select', node);
}
2022-09-14 11:26:01 +00:00
} else {
2022-09-06 12:03:37 +00:00
if (selected) {
2022-09-14 11:26:01 +00:00
_selectionKeys = { ...this.selectionKeys };
2022-09-06 12:03:37 +00:00
delete _selectionKeys[node.key];
this.$emit('node-unselect', node);
2022-09-14 11:26:01 +00:00
} else {
_selectionKeys = this.selectionKeys ? { ...this.selectionKeys } : {};
2022-09-06 12:03:37 +00:00
_selectionKeys[node.key] = true;
this.$emit('node-select', node);
}
}
return _selectionKeys;
},
onCheckboxChange(event) {
this.$emit('update:selectionKeys', event.selectionKeys);
2022-09-14 11:26:01 +00:00
if (event.check) this.$emit('node-select', event.node);
else this.$emit('node-unselect', event.node);
2022-09-06 12:03:37 +00:00
},
isSingleSelectionMode() {
return this.selectionMode === 'single';
},
isMultipleSelectionMode() {
return this.selectionMode === 'multiple';
},
onPage(event) {
this.d_first = event.first;
this.d_rows = event.rows;
let pageEvent = this.createLazyLoadEvent(event);
2022-09-14 11:26:01 +00:00
2022-09-06 12:03:37 +00:00
pageEvent.pageCount = event.pageCount;
pageEvent.page = event.page;
this.$emit('update:first', this.d_first);
this.$emit('update:rows', this.d_rows);
this.$emit('page', pageEvent);
},
resetPage() {
this.d_first = 0;
this.$emit('update:first', this.d_first);
},
getFilterColumnHeaderClass(column) {
2023-06-05 07:34:19 +00:00
return [this.cx('headerCell', { column }), this.columnProp(column, 'filterHeaderClass')];
2022-09-06 12:03:37 +00:00
},
onColumnHeaderClick(e) {
let event = e.originalEvent;
let column = e.column;
if (this.columnProp(column, 'sortable')) {
const targetNode = event.target;
const columnField = this.columnProp(column, 'sortField') || this.columnProp(column, 'field');
2022-09-14 11:26:01 +00:00
if (
2023-06-05 07:34:19 +00:00
DomHandler.getAttribute(targetNode, 'data-p-sortable-column') === true ||
DomHandler.getAttribute(targetNode, 'data-pc-section') === 'headerTitle' ||
DomHandler.getAttribute(targetNode, 'data-pc-section') === 'sortIcon' ||
DomHandler.getAttribute(targetNode.parentElement, 'data-pc-section') === 'sortIcon'
2022-09-14 11:26:01 +00:00
) {
2022-09-06 12:03:37 +00:00
DomHandler.clearSelection();
if (this.sortMode === 'single') {
if (this.d_sortField === columnField) {
2022-09-14 11:26:01 +00:00
if (this.removableSort && this.d_sortOrder * -1 === this.defaultSortOrder) {
2022-09-06 12:03:37 +00:00
this.d_sortOrder = null;
this.d_sortField = null;
2022-09-14 11:26:01 +00:00
} else {
2022-09-06 12:03:37 +00:00
this.d_sortOrder = this.d_sortOrder * -1;
}
2022-09-14 11:26:01 +00:00
} else {
2022-09-06 12:03:37 +00:00
this.d_sortOrder = this.defaultSortOrder;
this.d_sortField = columnField;
}
this.$emit('update:sortField', this.d_sortField);
this.$emit('update:sortOrder', this.d_sortOrder);
this.resetPage();
2022-09-14 11:26:01 +00:00
} else if (this.sortMode === 'multiple') {
2022-09-06 12:03:37 +00:00
let metaKey = event.metaKey || event.ctrlKey;
2022-09-14 11:26:01 +00:00
2022-09-06 12:03:37 +00:00
if (!metaKey) {
2022-09-14 11:26:01 +00:00
this.d_multiSortMeta = this.d_multiSortMeta.filter((meta) => meta.field === columnField);
2022-09-06 12:03:37 +00:00
}
this.addMultiSortField(columnField);
this.$emit('update:multiSortMeta', this.d_multiSortMeta);
}
this.$emit('sort', this.createLazyLoadEvent(event));
}
}
},
addMultiSortField(field) {
2022-09-14 11:26:01 +00:00
let index = this.d_multiSortMeta.findIndex((meta) => meta.field === field);
2022-09-06 12:03:37 +00:00
if (index >= 0) {
2022-09-14 11:26:01 +00:00
if (this.removableSort && this.d_multiSortMeta[index].order * -1 === this.defaultSortOrder) this.d_multiSortMeta.splice(index, 1);
else this.d_multiSortMeta[index] = { field: field, order: this.d_multiSortMeta[index].order * -1 };
} else {
this.d_multiSortMeta.push({ field: field, order: this.defaultSortOrder });
2022-09-06 12:03:37 +00:00
}
this.d_multiSortMeta = [...this.d_multiSortMeta];
},
sortSingle(nodes) {
return this.sortNodesSingle(nodes);
},
sortNodesSingle(nodes) {
let _nodes = [...nodes];
_nodes.sort((node1, node2) => {
const value1 = ObjectUtils.resolveFieldData(node1.data, this.d_sortField);
const value2 = ObjectUtils.resolveFieldData(node2.data, this.d_sortField);
let result = null;
2022-09-14 11:26:01 +00:00
if (value1 == null && value2 != null) result = -1;
else if (value1 != null && value2 == null) result = 1;
else if (value1 == null && value2 == null) result = 0;
else if (typeof value1 === 'string' && typeof value2 === 'string') result = value1.localeCompare(value2, undefined, { numeric: true });
else result = value1 < value2 ? -1 : value1 > value2 ? 1 : 0;
return this.d_sortOrder * result;
2022-09-06 12:03:37 +00:00
});
return _nodes;
},
sortMultiple(nodes) {
return this.sortNodesMultiple(nodes);
},
sortNodesMultiple(nodes) {
let _nodes = [...nodes];
2022-09-14 11:26:01 +00:00
2022-09-06 12:03:37 +00:00
_nodes.sort((node1, node2) => {
return this.multisortField(node1, node2, 0);
});
return _nodes;
},
multisortField(node1, node2, index) {
const value1 = ObjectUtils.resolveFieldData(node1.data, this.d_multiSortMeta[index].field);
const value2 = ObjectUtils.resolveFieldData(node2.data, this.d_multiSortMeta[index].field);
let result = null;
2022-09-14 11:26:01 +00:00
if (value1 == null && value2 != null) result = -1;
else if (value1 != null && value2 == null) result = 1;
else if (value1 == null && value2 == null) result = 0;
2022-09-06 12:03:37 +00:00
else {
2022-09-14 11:26:01 +00:00
if (value1 === value2) {
return this.d_multiSortMeta.length - 1 > index ? this.multisortField(node1, node2, index + 1) : 0;
} else {
if ((typeof value1 === 'string' || value1 instanceof String) && (typeof value2 === 'string' || value2 instanceof String)) return this.d_multiSortMeta[index].order * value1.localeCompare(value2, undefined, { numeric: true });
else result = value1 < value2 ? -1 : 1;
2022-09-06 12:03:37 +00:00
}
}
2022-09-14 11:26:01 +00:00
return this.d_multiSortMeta[index].order * result;
2022-09-06 12:03:37 +00:00
},
filter(value) {
let filteredNodes = [];
const strict = this.filterMode === 'strict';
for (let node of value) {
2022-09-14 11:26:01 +00:00
let copyNode = { ...node };
2022-09-06 12:03:37 +00:00
let localMatch = true;
let globalMatch = false;
for (let j = 0; j < this.columns.length; j++) {
let col = this.columns[j];
let filterField = this.columnProp(col, 'field');
//local
if (Object.prototype.hasOwnProperty.call(this.filters, this.columnProp(col, 'field'))) {
let filterMatchMode = this.columnProp(col, 'filterMatchMode') || 'startsWith';
let filterValue = this.filters[this.columnProp(col, 'field')];
let filterConstraint = FilterService.filters[filterMatchMode];
2022-09-14 11:26:01 +00:00
let paramsWithoutNode = { filterField, filterValue, filterConstraint, strict };
2022-09-06 12:03:37 +00:00
2022-09-14 11:26:01 +00:00
if (
(strict && !(this.findFilteredNodes(copyNode, paramsWithoutNode) || this.isFilterMatched(copyNode, paramsWithoutNode))) ||
(!strict && !(this.isFilterMatched(copyNode, paramsWithoutNode) || this.findFilteredNodes(copyNode, paramsWithoutNode)))
) {
localMatch = false;
2022-09-06 12:03:37 +00:00
}
if (!localMatch) {
break;
}
}
//global
if (this.hasGlobalFilter() && !globalMatch) {
2022-09-14 11:26:01 +00:00
let copyNodeForGlobal = { ...copyNode };
2022-09-06 12:03:37 +00:00
let filterValue = this.filters['global'];
let filterConstraint = FilterService.filters['contains'];
2022-09-14 11:26:01 +00:00
let globalFilterParamsWithoutNode = { filterField, filterValue, filterConstraint, strict };
if (
(strict && (this.findFilteredNodes(copyNodeForGlobal, globalFilterParamsWithoutNode) || this.isFilterMatched(copyNodeForGlobal, globalFilterParamsWithoutNode))) ||
(!strict && (this.isFilterMatched(copyNodeForGlobal, globalFilterParamsWithoutNode) || this.findFilteredNodes(copyNodeForGlobal, globalFilterParamsWithoutNode)))
) {
globalMatch = true;
copyNode = copyNodeForGlobal;
2022-09-06 12:03:37 +00:00
}
}
}
let matches = localMatch;
2022-09-14 11:26:01 +00:00
2022-09-06 12:03:37 +00:00
if (this.hasGlobalFilter()) {
matches = localMatch && globalMatch;
}
if (matches) {
filteredNodes.push(copyNode);
}
}
let filterEvent = this.createLazyLoadEvent(event);
2022-09-14 11:26:01 +00:00
2022-09-06 12:03:37 +00:00
filterEvent.filteredValue = filteredNodes;
this.$emit('filter', filterEvent);
return filteredNodes;
},
findFilteredNodes(node, paramsWithoutNode) {
if (node) {
let matched = false;
2022-09-14 11:26:01 +00:00
2022-09-06 12:03:37 +00:00
if (node.children) {
let childNodes = [...node.children];
2022-09-14 11:26:01 +00:00
2022-09-06 12:03:37 +00:00
node.children = [];
2022-09-14 11:26:01 +00:00
2022-09-06 12:03:37 +00:00
for (let childNode of childNodes) {
2022-09-14 11:26:01 +00:00
let copyChildNode = { ...childNode };
2022-09-06 12:03:37 +00:00
if (this.isFilterMatched(copyChildNode, paramsWithoutNode)) {
matched = true;
node.children.push(copyChildNode);
}
}
}
if (matched) {
return true;
}
}
},
2022-09-14 11:26:01 +00:00
isFilterMatched(node, { filterField, filterValue, filterConstraint, strict }) {
2022-09-06 12:03:37 +00:00
let matched = false;
let dataFieldValue = ObjectUtils.resolveFieldData(node.data, filterField);
2022-09-14 11:26:01 +00:00
2022-09-06 12:03:37 +00:00
if (filterConstraint(dataFieldValue, filterValue, this.filterLocale)) {
matched = true;
}
if (!matched || (strict && !this.isNodeLeaf(node))) {
2022-09-14 11:26:01 +00:00
matched = this.findFilteredNodes(node, { filterField, filterValue, filterConstraint, strict }) || matched;
2022-09-06 12:03:37 +00:00
}
return matched;
},
isNodeSelected(node) {
2022-09-14 11:26:01 +00:00
return this.selectionMode && this.selectionKeys ? this.selectionKeys[node.key] === true : false;
2022-09-06 12:03:37 +00:00
},
isNodeLeaf(node) {
return node.leaf === false ? false : !(node.children && node.children.length);
},
createLazyLoadEvent(event) {
let filterMatchModes;
2022-09-14 11:26:01 +00:00
2022-09-06 12:03:37 +00:00
if (this.hasFilters()) {
filterMatchModes = {};
2022-09-14 11:26:01 +00:00
this.columns.forEach((col) => {
2022-09-06 12:03:37 +00:00
if (this.columnProp(col, 'field')) {
filterMatchModes[col.props.field] = this.columnProp(col, 'filterMatchMode');
}
});
}
return {
originalEvent: event,
first: this.d_first,
rows: this.d_rows,
sortField: this.d_sortField,
sortOrder: this.d_sortOrder,
multiSortMeta: this.d_multiSortMeta,
filters: this.filters,
filterMatchModes: filterMatchModes
};
},
onColumnResizeStart(event) {
let containerLeft = DomHandler.getOffset(this.$el).left;
2022-09-14 11:26:01 +00:00
2022-09-06 12:03:37 +00:00
this.resizeColumnElement = event.target.parentElement;
this.columnResizing = true;
2022-09-14 11:26:01 +00:00
this.lastResizeHelperX = event.pageX - containerLeft + this.$el.scrollLeft;
2022-09-06 12:03:37 +00:00
this.bindColumnResizeEvents();
2022-09-06 12:03:37 +00:00
},
onColumnResize(event) {
let containerLeft = DomHandler.getOffset(this.$el).left;
2022-09-14 11:26:01 +00:00
2022-09-06 12:03:37 +00:00
DomHandler.addClass(this.$el, 'p-unselectable-text');
this.$refs.resizeHelper.style.height = this.$el.offsetHeight + 'px';
this.$refs.resizeHelper.style.top = 0 + 'px';
2022-09-14 11:26:01 +00:00
this.$refs.resizeHelper.style.left = event.pageX - containerLeft + this.$el.scrollLeft + 'px';
2022-09-06 12:03:37 +00:00
this.$refs.resizeHelper.style.display = 'block';
},
onColumnResizeEnd() {
2022-09-14 11:26:01 +00:00
let delta = this.$refs.resizeHelper.offsetLeft - this.lastResizeHelperX;
2022-09-06 12:03:37 +00:00
let columnWidth = this.resizeColumnElement.offsetWidth;
let newColumnWidth = columnWidth + delta;
2022-09-14 11:26:01 +00:00
let minWidth = this.resizeColumnElement.style.minWidth || 15;
2022-09-06 12:03:37 +00:00
if (columnWidth + delta > parseInt(minWidth, 10)) {
if (this.columnResizeMode === 'fit') {
let nextColumn = this.resizeColumnElement.nextElementSibling;
let nextColumnWidth = nextColumn.offsetWidth - delta;
if (newColumnWidth > 15 && nextColumnWidth > 15) {
if (!this.scrollable) {
this.resizeColumnElement.style.width = newColumnWidth + 'px';
2022-09-14 11:26:01 +00:00
if (nextColumn) {
2022-09-06 12:03:37 +00:00
nextColumn.style.width = nextColumnWidth + 'px';
}
2022-09-14 11:26:01 +00:00
} else {
2022-09-06 12:03:37 +00:00
this.resizeTableCells(newColumnWidth, nextColumnWidth);
}
}
2022-09-14 11:26:01 +00:00
} else if (this.columnResizeMode === 'expand') {
2022-09-06 12:03:37 +00:00
this.$refs.table.style.width = this.$refs.table.offsetWidth + delta + 'px';
2022-09-14 11:26:01 +00:00
if (!this.scrollable) this.resizeColumnElement.style.width = newColumnWidth + 'px';
else this.resizeTableCells(newColumnWidth);
2022-09-06 12:03:37 +00:00
}
this.$emit('column-resize-end', {
element: this.resizeColumnElement,
delta: delta
});
}
this.$refs.resizeHelper.style.display = 'none';
this.resizeColumn = null;
DomHandler.removeClass(this.$el, 'p-unselectable-text');
this.unbindColumnResizeEvents();
},
resizeTableCells(newColumnWidth, nextColumnWidth) {
let colIndex = DomHandler.index(this.resizeColumnElement);
let children = this.$refs.table.children;
2022-09-14 11:26:01 +00:00
2022-09-06 12:03:37 +00:00
for (let child of children) {
for (let row of child.children) {
let resizeCell = row.children[colIndex];
2022-09-14 11:26:01 +00:00
2022-09-06 12:03:37 +00:00
resizeCell.style.flex = '0 0 ' + newColumnWidth + 'px';
if (this.columnResizeMode === 'fit') {
let nextCell = resizeCell.nextElementSibling;
2022-09-14 11:26:01 +00:00
2022-09-06 12:03:37 +00:00
if (nextCell) {
nextCell.style.flex = '0 0 ' + nextColumnWidth + 'px';
}
}
}
}
},
bindColumnResizeEvents() {
2022-09-06 12:03:37 +00:00
if (!this.documentColumnResizeListener) {
this.documentColumnResizeListener = document.addEventListener('mousemove', (event) => {
2022-09-14 11:26:01 +00:00
if (this.columnResizing) {
2022-09-06 12:03:37 +00:00
this.onColumnResize(event);
}
});
}
if (!this.documentColumnResizeEndListener) {
this.documentColumnResizeEndListener = document.addEventListener('mouseup', () => {
2022-09-14 11:26:01 +00:00
if (this.columnResizing) {
2022-09-06 12:03:37 +00:00
this.columnResizing = false;
this.onColumnResizeEnd();
}
});
}
},
unbindColumnResizeEvents() {
if (this.documentColumnResizeListener) {
document.removeEventListener('document', this.documentColumnResizeListener);
this.documentColumnResizeListener = null;
}
if (this.documentColumnResizeEndListener) {
document.removeEventListener('document', this.documentColumnResizeEndListener);
2022-09-14 11:26:01 +00:00
this.documentColumnResizeEndListener = null;
2022-09-06 12:03:37 +00:00
}
},
onColumnKeyDown(event, col) {
2023-06-05 07:34:19 +00:00
if (event.code === 'Enter' && event.currentTarget.nodeName === 'TH' && DomHandler.getAttribute(event.currentTarget, 'data-p-sortable-column')) {
2022-09-06 12:03:37 +00:00
this.onColumnHeaderClick(event, col);
}
},
hasColumnFilter() {
if (this.columns) {
for (let col of this.columns) {
if (col.children && col.children.filter) {
return true;
}
}
}
return false;
},
hasFilters() {
return this.filters && Object.keys(this.filters).length > 0 && this.filters.constructor === Object;
},
hasGlobalFilter() {
return this.filters && Object.prototype.hasOwnProperty.call(this.filters, 'global');
},
updateScrollWidth() {
this.$refs.table.style.width = this.$refs.table.scrollWidth + 'px';
2022-12-08 11:04:25 +00:00
},
getItemLabel(node) {
return node.data.name;
},
setTabindex(node, index) {
if (this.isNodeSelected(node)) {
this.hasASelectedNode = true;
return 0;
}
if (this.selectionMode) {
if (!this.isNodeSelected(node) && index === 0 && !this.hasASelectedNode) return 0;
} else if (!this.selectionMode && index === 0) {
return 0;
}
return -1;
2022-09-06 12:03:37 +00:00
}
},
computed: {
columns() {
let cols = [];
let children = this.$slots.default();
2022-09-14 11:26:01 +00:00
children.forEach((child) => {
if (child.children && child.children instanceof Array) cols = [...cols, ...child.children];
else if (child.type.name === 'Column') cols.push(child);
2022-09-06 12:03:37 +00:00
});
return cols;
},
processedData() {
if (this.lazy) {
return this.value;
2022-09-14 11:26:01 +00:00
} else {
2022-09-06 12:03:37 +00:00
if (this.value && this.value.length) {
let data = this.value;
if (this.sorted) {
2022-09-14 11:26:01 +00:00
if (this.sortMode === 'single') data = this.sortSingle(data);
else if (this.sortMode === 'multiple') data = this.sortMultiple(data);
2022-09-06 12:03:37 +00:00
}
if (this.hasFilters()) {
data = this.filter(data);
}
return data;
2022-09-14 11:26:01 +00:00
} else {
2022-09-06 12:03:37 +00:00
return null;
}
}
},
dataToRender() {
const data = this.processedData;
if (this.paginator) {
const first = this.lazy ? 0 : this.d_first;
2022-09-14 11:26:01 +00:00
2022-09-06 12:03:37 +00:00
return data.slice(first, first + this.d_rows);
2022-09-14 11:26:01 +00:00
} else {
2022-09-06 12:03:37 +00:00
return data;
}
},
empty() {
const data = this.processedData;
2022-09-14 11:26:01 +00:00
return !data || data.length === 0;
2022-09-06 12:03:37 +00:00
},
sorted() {
return this.d_sortField || (this.d_multiSortMeta && this.d_multiSortMeta.length > 0);
},
hasFooter() {
let hasFooter = false;
for (let col of this.columns) {
2022-09-14 11:26:01 +00:00
if (this.columnProp(col, 'footer') || (col.children && col.children.footer)) {
2022-09-06 12:03:37 +00:00
hasFooter = true;
break;
}
}
return hasFooter;
},
paginatorTop() {
return this.paginator && (this.paginatorPosition !== 'bottom' || this.paginatorPosition === 'both');
},
paginatorBottom() {
return this.paginator && (this.paginatorPosition !== 'top' || this.paginatorPosition === 'both');
},
singleSelectionMode() {
return this.selectionMode && this.selectionMode === 'single';
},
multipleSelectionMode() {
return this.selectionMode && this.selectionMode === 'multiple';
},
rowSelectionMode() {
return this.singleSelectionMode || this.multipleSelectionMode;
},
totalRecordsLength() {
if (this.lazy) {
return this.totalRecords;
2022-09-14 11:26:01 +00:00
} else {
2022-09-06 12:03:37 +00:00
const data = this.processedData;
2022-09-14 11:26:01 +00:00
2022-09-06 12:03:37 +00:00
return data ? data.length : 0;
}
}
},
components: {
2022-09-14 11:26:01 +00:00
TTRow: TreeTableRow,
TTPaginator: Paginator,
TTHeaderCell: HeaderCell,
TTFooterCell: FooterCell,
SpinnerIcon: SpinnerIcon
2022-09-06 12:03:37 +00:00
}
2022-09-14 11:26:01 +00:00
};
2022-09-06 12:03:37 +00:00
</script>