Fixed #6994 - DataTable: Frozen Column with Basic Filtering
parent
1536d128ac
commit
699c248538
|
@ -0,0 +1,190 @@
|
|||
<template>
|
||||
<th
|
||||
v-if="!columnProp('hidden') && (rowGroupMode !== 'subheader' || groupRowsBy !== columnProp('field'))"
|
||||
:style="getFilterColumnHeaderStyle"
|
||||
:class="getFilterColumnHeaderClass"
|
||||
v-bind="{ ...getColumnPT('root'), ...getColumnPT('headerCell') }"
|
||||
:data-p-frozen-column="columnProp('frozen')"
|
||||
>
|
||||
<DTHeaderCheckbox v-if="columnProp('selectionMode') === 'multiple'" :checked="allRowsSelected" :disabled="empty" @change="$emit('checkbox-change', $event)" :column="column" :unstyled="unstyled" :pt="pt" />
|
||||
<DTColumnFilter
|
||||
v-if="column.children && column.children.filter"
|
||||
:field="columnProp('filterField') || columnProp('field')"
|
||||
:type="columnProp('dataType')"
|
||||
display="row"
|
||||
:showMenu="columnProp('showFilterMenu')"
|
||||
:filterElement="column.children && column.children.filter"
|
||||
:filterHeaderTemplate="column.children && column.children.filterheader"
|
||||
:filterFooterTemplate="column.children && column.children.filterfooter"
|
||||
:filterClearTemplate="column.children && column.children.filterclear"
|
||||
:filterApplyTemplate="column.children && column.children.filterapply"
|
||||
:filterIconTemplate="column.children && column.children.filtericon"
|
||||
:filterAddIconTemplate="column.children && column.children.filteraddicon"
|
||||
:filterRemoveIconTemplate="column.children && column.children.filterremoveicon"
|
||||
:filterClearIconTemplate="column.children && column.children.filterclearicon"
|
||||
:filters="filters"
|
||||
:filtersStore="filtersStore"
|
||||
:filterInputProps="filterInputProps"
|
||||
:filterButtonProps="filterButtonProps"
|
||||
@filter-change="$emit('filter-change', $event)"
|
||||
@filter-apply="$emit('filter-apply')"
|
||||
:filterMenuStyle="columnProp('filterMenuStyle')"
|
||||
:filterMenuClass="columnProp('filterMenuClass')"
|
||||
:showOperator="columnProp('showFilterOperator')"
|
||||
:showClearButton="columnProp('showClearButton')"
|
||||
:showApplyButton="columnProp('showApplyButton')"
|
||||
:showMatchModes="columnProp('showFilterMatchModes')"
|
||||
:showAddButton="columnProp('showAddButton')"
|
||||
:matchModeOptions="columnProp('filterMatchModeOptions')"
|
||||
:maxConstraints="columnProp('maxConstraints')"
|
||||
@operator-change="$emit('operator-change', $event)"
|
||||
@matchmode-change="$emit('matchmode-change', $event)"
|
||||
@constraint-add="$emit('constraint-add', $event)"
|
||||
@constraint-remove="$emit('constraint-remove', $event)"
|
||||
@apply-click="$emit('apply-click', $event)"
|
||||
:column="column"
|
||||
:unstyled="unstyled"
|
||||
:pt="pt"
|
||||
/>
|
||||
</th>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getNextElementSibling, getOuterWidth, getPreviousElementSibling } from '@primeuix/utils/dom';
|
||||
import BaseComponent from '@primevue/core/basecomponent';
|
||||
import { getVNodeProp } from '@primevue/core/utils';
|
||||
import { mergeProps } from 'vue';
|
||||
import ColumnFilter from './ColumnFilter.vue';
|
||||
import HeaderCheckbox from './HeaderCheckbox.vue';
|
||||
|
||||
export default {
|
||||
name: 'FilterHeaderCell',
|
||||
hostName: 'DataTable',
|
||||
extends: BaseComponent,
|
||||
emits: ['checkbox-change', 'filter-change', 'filter-apply', 'operator-change', 'matchmode-change', 'constraint-add', 'constraint-remove', 'apply-click'],
|
||||
props: {
|
||||
column: {
|
||||
type: Object,
|
||||
default: null
|
||||
},
|
||||
index: {
|
||||
type: Number,
|
||||
default: null
|
||||
},
|
||||
allRowsSelected: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
empty: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
display: {
|
||||
type: String,
|
||||
default: 'row'
|
||||
},
|
||||
filters: {
|
||||
type: Object,
|
||||
default: null
|
||||
},
|
||||
filtersStore: {
|
||||
type: Object,
|
||||
default: null
|
||||
},
|
||||
rowGroupMode: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
groupRowsBy: {
|
||||
type: [Array, String, Function],
|
||||
default: null
|
||||
},
|
||||
filterInputProps: {
|
||||
type: null,
|
||||
default: null
|
||||
},
|
||||
filterButtonProps: {
|
||||
type: null,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
styleObject: {}
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
if (this.columnProp('frozen')) {
|
||||
this.updateStickyPosition();
|
||||
}
|
||||
},
|
||||
updated() {
|
||||
if (this.columnProp('frozen')) {
|
||||
this.updateStickyPosition();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
columnProp(prop) {
|
||||
return getVNodeProp(this.column, prop);
|
||||
},
|
||||
getColumnPT(key) {
|
||||
if (!this.column) return null;
|
||||
|
||||
const columnMetaData = {
|
||||
props: this.column.props,
|
||||
parent: {
|
||||
instance: this,
|
||||
props: this.$props,
|
||||
state: this.$data
|
||||
},
|
||||
context: {
|
||||
index: this.index
|
||||
}
|
||||
};
|
||||
|
||||
return mergeProps(this.ptm(`column.${key}`, { column: columnMetaData }), this.ptm(`column.${key}`, columnMetaData), this.ptmo(this.getColumnProp(), key, columnMetaData));
|
||||
},
|
||||
getColumnProp() {
|
||||
return this.column.props && this.column.props.pt ? this.column.props.pt : undefined; //@todo
|
||||
},
|
||||
updateStickyPosition() {
|
||||
if (this.columnProp('frozen')) {
|
||||
let align = this.columnProp('alignFrozen');
|
||||
|
||||
if (align === 'right') {
|
||||
let pos = 0;
|
||||
let next = getNextElementSibling(this.$el, '[data-p-frozen-column="true"]');
|
||||
|
||||
if (next) {
|
||||
pos = getOuterWidth(next) + parseFloat(next.style['inset-inline-end'] || 0);
|
||||
}
|
||||
|
||||
this.styleObject.insetInlineEnd = pos + 'px';
|
||||
} else {
|
||||
console.log(getPreviousElementSibling(this.$el, '[data-p-frozen-column="true"]'));
|
||||
let pos = 0;
|
||||
let prev = getPreviousElementSibling(this.$el, '[data-p-frozen-column="true"]');
|
||||
|
||||
if (prev) {
|
||||
pos = getOuterWidth(prev) + parseFloat(prev.style['inset-inline-start'] || 0);
|
||||
}
|
||||
|
||||
this.styleObject.insetInlineStart = pos + 'px';
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
getFilterColumnHeaderClass() {
|
||||
return [this.cx('headerCell', { column: this.column }), this.columnProp('filterHeaderClass'), this.columnProp('class')];
|
||||
},
|
||||
getFilterColumnHeaderStyle() {
|
||||
return this.columnProp('frozen') ? [this.columnProp('filterHeaderStyle'), this.columnProp('style'), this.styleObject] : [this.columnProp('filterHeaderStyle'), this.columnProp('style')];
|
||||
}
|
||||
},
|
||||
components: {
|
||||
DTHeaderCheckbox: HeaderCheckbox,
|
||||
DTColumnFilter: ColumnFilter
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -79,53 +79,28 @@
|
|||
</template>
|
||||
<tr v-if="filterDisplay === 'row'" role="row" v-bind="ptm('headerRow')">
|
||||
<template v-for="(col, i) of columns" :key="columnProp(col, 'columnKey') || columnProp(col, 'field') || i">
|
||||
<th
|
||||
<DTFilterHeaderCell
|
||||
v-if="!columnProp(col, 'hidden') && (rowGroupMode !== 'subheader' || groupRowsBy !== columnProp(col, 'field'))"
|
||||
:style="getFilterColumnHeaderStyle(col)"
|
||||
:class="getFilterColumnHeaderClass(col)"
|
||||
v-bind="{ ...getColumnPT(col, 'root', i), ...getColumnPT(col, 'headerCell', i) }"
|
||||
>
|
||||
<DTHeaderCheckbox v-if="columnProp(col, 'selectionMode') === 'multiple'" :checked="allRowsSelected" :disabled="empty" @change="$emit('checkbox-change', $event)" :column="col" :unstyled="unstyled" :pt="pt" />
|
||||
<DTColumnFilter
|
||||
v-if="col.children && col.children.filter"
|
||||
:field="columnProp(col, 'filterField') || columnProp(col, 'field')"
|
||||
:type="columnProp(col, 'dataType')"
|
||||
display="row"
|
||||
:showMenu="columnProp(col, 'showFilterMenu')"
|
||||
:filterElement="col.children && col.children.filter"
|
||||
:filterHeaderTemplate="col.children && col.children.filterheader"
|
||||
:filterFooterTemplate="col.children && col.children.filterfooter"
|
||||
:filterClearTemplate="col.children && col.children.filterclear"
|
||||
:filterApplyTemplate="col.children && col.children.filterapply"
|
||||
:filterIconTemplate="col.children && col.children.filtericon"
|
||||
:filterAddIconTemplate="col.children && col.children.filteraddicon"
|
||||
:filterRemoveIconTemplate="col.children && col.children.filterremoveicon"
|
||||
:filterClearIconTemplate="col.children && col.children.filterclearicon"
|
||||
:filters="filters"
|
||||
:filtersStore="filtersStore"
|
||||
:filterInputProps="filterInputProps"
|
||||
:filterButtonProps="filterButtonProps"
|
||||
@filter-change="$emit('filter-change', $event)"
|
||||
@filter-apply="$emit('filter-apply')"
|
||||
:filterMenuStyle="columnProp(col, 'filterMenuStyle')"
|
||||
:filterMenuClass="columnProp(col, 'filterMenuClass')"
|
||||
:showOperator="columnProp(col, 'showFilterOperator')"
|
||||
:showClearButton="columnProp(col, 'showClearButton')"
|
||||
:showApplyButton="columnProp(col, 'showApplyButton')"
|
||||
:showMatchModes="columnProp(col, 'showFilterMatchModes')"
|
||||
:showAddButton="columnProp(col, 'showAddButton')"
|
||||
:matchModeOptions="columnProp(col, 'filterMatchModeOptions')"
|
||||
:maxConstraints="columnProp(col, 'maxConstraints')"
|
||||
@operator-change="$emit('operator-change', $event)"
|
||||
@matchmode-change="$emit('matchmode-change', $event)"
|
||||
@constraint-add="$emit('constraint-add', $event)"
|
||||
@constraint-remove="$emit('constraint-remove', $event)"
|
||||
@apply-click="$emit('apply-click', $event)"
|
||||
:column="col"
|
||||
:unstyled="unstyled"
|
||||
:pt="pt"
|
||||
/>
|
||||
</th>
|
||||
:column="col"
|
||||
:index="i"
|
||||
:allRowsSelected="allRowsSelected"
|
||||
:empty="empty"
|
||||
display="row"
|
||||
:filters="filters"
|
||||
:filtersStore="filtersStore"
|
||||
:filterInputProps="filterInputProps"
|
||||
:filterButtonProps="filterButtonProps"
|
||||
@filter-change="$emit('filter-change', $event)"
|
||||
@filter-apply="$emit('filter-apply')"
|
||||
@operator-change="$emit('operator-change', $event)"
|
||||
@matchmode-change="$emit('matchmode-change', $event)"
|
||||
@constraint-add="$emit('constraint-add', $event)"
|
||||
@constraint-remove="$emit('constraint-remove', $event)"
|
||||
@apply-click="$emit('apply-click', $event)"
|
||||
@change="$emit('checkbox-change', $event)"
|
||||
:unstyled="unstyled"
|
||||
:pt="pt"
|
||||
/>
|
||||
</template>
|
||||
</tr>
|
||||
</thead>
|
||||
|
@ -135,9 +110,8 @@
|
|||
import BaseComponent from '@primevue/core/basecomponent';
|
||||
import { HelperSet, getVNodeProp } from '@primevue/core/utils';
|
||||
import { mergeProps } from 'vue';
|
||||
import ColumnFilter from './ColumnFilter.vue';
|
||||
import FilterHeaderCell from './FilterHeaderCell.vue';
|
||||
import HeaderCell from './HeaderCell.vue';
|
||||
import HeaderCheckbox from './HeaderCheckbox.vue';
|
||||
|
||||
export default {
|
||||
name: 'TableHeader',
|
||||
|
@ -338,8 +312,7 @@ export default {
|
|||
},
|
||||
components: {
|
||||
DTHeaderCell: HeaderCell,
|
||||
DTHeaderCheckbox: HeaderCheckbox,
|
||||
DTColumnFilter: ColumnFilter
|
||||
DTFilterHeaderCell: FilterHeaderCell
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -620,11 +620,11 @@ const classes = {
|
|||
],
|
||||
thead: 'p-datatable-thead',
|
||||
headerCell: ({ instance, props, column }) =>
|
||||
column && !instance.columnProp(column, 'hidden') && (props.rowGroupMode !== 'subheader' || props.groupRowsBy !== instance.columnProp(column, 'field'))
|
||||
column && !instance.columnProp('hidden') && (props.rowGroupMode !== 'subheader' || props.groupRowsBy !== instance.columnProp(column, 'field'))
|
||||
? [
|
||||
'p-datatable-header-cell',
|
||||
{
|
||||
'p-datatable-frozen-column': instance.columnProp(column, 'frozen')
|
||||
'p-datatable-frozen-column': instance.columnProp('frozen')
|
||||
}
|
||||
]
|
||||
: [
|
||||
|
@ -653,7 +653,7 @@ const classes = {
|
|||
filterElementContainer: 'p-datatable-filter-element-container',
|
||||
pcColumnFilterButton: 'p-datatable-column-filter-button',
|
||||
pcColumnFilterClearButton: 'p-datatable-column-filter-clear-button',
|
||||
filterOverlay: ({ instance, props }) => [
|
||||
filterOverlay: ({ props }) => [
|
||||
'p-datatable-filter-overlay p-component',
|
||||
{
|
||||
'p-datatable-filter-overlay-popover': props.display === 'menu'
|
||||
|
|
Loading…
Reference in New Issue