primevue-mirror/src/components/datatable/TableHeader.vue

214 lines
9.3 KiB
Vue
Raw Normal View History

<template>
<thead class="p-datatable-thead">
<template v-if="!columnGroup">
<tr>
<template v-for="(col,i) of columns">
2020-09-24 08:30:11 +00:00
<th v-if="rowGroupMode !== 'subheader' || (groupRowsBy !== col.props?.field)" :tabindex="col.props?.sortable ? '0' : null" @keydown="onColumnKeyDown($event, col)"
:key="col.props?.columnKey||col.props?.field||i" :style="col.props?.headerStyle" :class="getColumnHeaderClass(col)"
@click="onColumnHeaderClick($event, col)" @mousedown="onColumnHeaderMouseDown($event, col)"
@dragstart="onColumnHeaderDragStart($event)" @dragover="onColumnHeaderDragOver($event)" @dragleave="onColumnHeaderDragLeave($event)" @drop="onColumnHeaderDrop($event)"
2020-09-24 08:30:11 +00:00
:colspan="col.props?.colspan" :rowspan="col.props?.rowspan" :aria-sort="getAriaSort(col)">
2020-05-02 09:19:17 +00:00
<span class="p-column-resizer" @mousedown="onColumnResizeStart($event)" v-if="resizableColumns"></span>
2020-09-23 17:55:00 +00:00
<component :is="col.children.header" :column="col" v-if="col.children && col.children.header"/>
2020-09-24 08:30:11 +00:00
<span class="p-column-title" v-if="col.props?.header">{{col.props?.header}}</span>
<span v-if="col.props?.sortable" :class="getSortableColumnIcon(col)"></span>
<span v-if="isMultiSorted(col)" class="p-sortable-column-badge">{{getMultiSortMetaIndex(col) + 1}}</span>
2020-09-24 08:30:11 +00:00
<DTHeaderCheckbox :checked="allRowsSelected" @change="onHeaderCheckboxChange($event)" :disabled="empty" v-if="col.props?.selectionMode ==='multiple' && !hasColumnFilter()" />
</th>
</template>
</tr>
<tr v-if="hasColumnFilter()">
<template v-for="(col,i) of columns">
2020-09-24 08:30:11 +00:00
<th v-if="rowGroupMode !== 'subheader' || (groupRowsBy !== col.props?.field)" :key="col.props?.columnKey||col.props?.field||i"
:class="getFilterColumnHeaderClass(col)" :style="col.props?.filterHeaderStyle">
2020-09-23 17:55:00 +00:00
<component :is="col.children.filter" :column="col" v-if="col.children && col.children.filter"/>
2020-09-24 08:30:11 +00:00
<DTHeaderCheckbox :checked="allRowsSelected" @change="onHeaderCheckboxChange($event)" :disabled="empty" v-if="col.props?.selectionMode ==='multiple'" />
</th>
</template>
</tr>
</template>
<template v-else>
2020-09-23 17:55:00 +00:00
<tr v-for="(row,i) of columnGroup.children.default()" :key="i">
2020-09-24 08:30:11 +00:00
<th v-for="(col,i) of row.children.default()" :key="col.props?.columnKey||col.props?.field||i" :style="col.props?.headerStyle" :class="getColumnHeaderClass(col)" :tabindex="col.props?.sortable ? '0' : null"
2020-03-04 10:36:14 +00:00
@click="onColumnHeaderClick($event, col)" @keydown="onColumnKeyDown($event, col)" @dragstart="onColumnHeaderDragStart($event)" @dragover="onColumnHeaderDragOver($event)" @dragleave="onColumnHeaderDragLeave($event)" @drop="onColumnHeaderDrop($event)"
2020-09-24 08:30:11 +00:00
:colspan="col.props?.colspan" :rowspan="col.props?.rowspan" :aria-sort="getAriaSort(col)">
2020-09-23 17:55:00 +00:00
<component :is="col.children.header" :column="col" v-if="col.children && col.children.header"/>
2020-09-24 08:30:11 +00:00
<span class="p-column-title" v-if="col.props?.header">{{col.props?.header}}</span>
<span v-if="col.props?.sortable" :class="getSortableColumnIcon(col)"></span>
<span v-if="isMultiSorted(col)" class="p-sortable-column-badge">{{getMultiSortMetaIndex(col) + 1}}</span>
2020-09-23 17:55:00 +00:00
<component :is="col.children.filter" :column="col" v-if="col.children && col.children.filter"/>
2020-09-24 08:30:11 +00:00
<DTHeaderCheckbox :checked="allRowsSelected" @change="onHeaderCheckboxChange($event)" :disabled="empty" v-if="col.props?.selectionMode ==='multiple'" />
</th>
</tr>
</template>
</thead>
</template>
<script>
import {DomHandler} from 'primevue/utils';
import HeaderCheckbox from './HeaderCheckbox.vue';
export default {
emits: ['column-click', 'column-mousedown', 'column-dragstart', 'column-dragover', 'column-dragleave', 'column-drop',
'column-resizestart', 'checkbox-change', 'column-click'],
props: {
columnGroup: {
type: null,
default: null
},
columns: {
type: null,
default: null
},
rowGroupMode: {
type: String,
default: null
},
groupRowsBy: {
type: [Array,String],
default: null
},
resizableColumns: {
type: Boolean,
default: false
},
allRowsSelected: {
type: Boolean,
default: false
},
empty: {
type: Boolean,
default: false
},
sortMode: {
type: String,
default: 'single'
},
sortField: {
2020-12-08 11:16:38 +00:00
type: [String, Function],
default: null
},
sortOrder: {
type: Number,
default: null
},
multiSortMeta: {
type: Array,
default: null
}
},
methods: {
isMultiSorted(column) {
2020-09-24 08:30:11 +00:00
return column.props?.sortable && this.getMultiSortMetaIndex(column) > -1
},
isColumnSorted(column) {
2020-09-24 08:30:11 +00:00
return this.sortMode === 'single' ? (this.sortField && (this.sortField === column.props?.field || this.sortField === column.props?.sortField)) : this.isMultiSorted(column);
},
getColumnHeaderClass(column) {
2020-09-24 08:30:11 +00:00
return [column.props?.headerClass,
{'p-sortable-column': column.props?.sortable},
{'p-resizable-column': this.resizableColumns},
{'p-highlight': this.isColumnSorted(column)}
];
},
getFilterColumnHeaderClass(column) {
2020-09-24 08:30:11 +00:00
return ['p-filter-column', column.props?.filterHeaderClass];
},
getSortableColumnIcon(column) {
let sorted = false;
let sortOrder = null;
if (this.sortMode === 'single') {
2020-09-24 08:30:11 +00:00
sorted = this.sortField && (this.sortField === column.props?.field || this.sortField === column.props?.sortField);
sortOrder = sorted ? this.sortOrder: 0;
}
else if (this.sortMode === 'multiple') {
let metaIndex = this.getMultiSortMetaIndex(column);
if (metaIndex > -1) {
sorted = true;
sortOrder = this.multiSortMeta[metaIndex].order;
}
}
return [
'p-sortable-column-icon pi pi-fw', {
2020-04-17 19:38:11 +00:00
'pi-sort-alt': !sorted,
'pi-sort-amount-up-alt': sorted && sortOrder > 0,
'pi-sort-amount-down': sorted && sortOrder < 0
}
];
},
getMultiSortMetaIndex(column) {
let index = -1;
for (let i = 0; i < this.multiSortMeta.length; i++) {
let meta = this.multiSortMeta[i];
2020-09-24 08:30:11 +00:00
if (meta.field === column.props?.field || meta.field === column.props?.sortField) {
index = i;
break;
}
}
return index;
},
onColumnHeaderClick(event, col) {
this.$emit('column-click', {originalEvent: event, column: col});
},
onColumnHeaderMouseDown(event, col) {
this.$emit('column-mousedown', {originalEvent: event, column: col});
},
onColumnHeaderDragStart(event) {
this.$emit('column-dragstart', event);
},
onColumnHeaderDragOver(event) {
this.$emit('column-dragover', event);
},
onColumnHeaderDragLeave(event) {
this.$emit('column-dragleave', event);
},
onColumnHeaderDrop(event) {
this.$emit('column-drop', event);
},
onColumnResizeStart(event) {
this.$emit('column-resizestart', event);
},
onHeaderCheckboxChange(event) {
this.$emit('checkbox-change', event);
},
onColumnKeyDown(event, col) {
if (event.which === 13 && event.currentTarget.nodeName === 'TH' && DomHandler.hasClass(event.currentTarget, 'p-sortable-column')) {
this.$emit('column-click', {originalEvent: event, column: col});
}
},
getAriaSort(column) {
2020-09-24 08:30:11 +00:00
if (column.props?.sortable) {
const sortIcon = this.getSortableColumnIcon(column);
2020-04-17 19:38:11 +00:00
if (sortIcon[1]['pi-sort-amount-down'])
return 'descending';
2020-04-17 19:38:11 +00:00
else if (sortIcon[1]['pi-sort-amount-up-alt'])
return 'ascending';
else
return 'none';
}
else {
return null;
}
},
hasColumnFilter() {
if (this.columns) {
for (let col of this.columns) {
2020-09-23 17:55:00 +00:00
if (col.children && col.children.filter) {
return true;
}
}
}
return false;
}
},
components: {
'DTHeaderCheckbox': HeaderCheckbox
}
}
</script>