Refactor #4149 - For DataTable & Column & ColumnGroup

pull/4172/head
Tuğçe Küçükoğlu 2023-07-19 15:05:06 +03:00
parent dcd76d09cc
commit 97d112a2e0
13 changed files with 195 additions and 37 deletions

View File

@ -141,6 +141,10 @@ export interface ColumnPassThroughOptions {
* Uses to pass attributes to the filter menu button's DOM element.
*/
filterMenuButton?: ColumnPassThroughOptionType;
/**
* Uses to pass attributes to the filter menu icon's DOM element.
*/
filterMenuIcon?: ColumnPassThroughOptionType;
/**
* Uses to pass attributes to the header filter clear button's DOM element.
*/
@ -609,6 +613,35 @@ export interface ColumnContext {
* @defaultValue false
*/
resizable: boolean;
/**
* Current size state of the table.
*/
size: string;
/**
* Current gridlines state of the table as a boolean.
* @defaultValue false
*/
showGridlines: boolean;
/**
* Current highlighted state of the filter row item as a boolean.
* @defaultValue false
*/
highlighted: boolean;
/**
* Current hidden state of the filter clear button of a column as a boolean.
* @defaultValue false
*/
hidden: boolean;
/**
* Current visible state of the filter menu of a column as a boolean.
* @defaultValue false
*/
overlayVisible: boolean;
/**
* Current active state of the filter menu of a column as a boolean.
* @defaultValue false
*/
active: boolean;
}
/**

View File

@ -72,6 +72,11 @@ export interface ColumnGroupContext {
* Current type of the column group.
*/
type: string;
/**
* Current scrollable state of column group as a boolean.
* @defaultValue false
*/
scrollable: boolean;
}
/**

View File

@ -46,8 +46,8 @@
</template>
<template v-else-if="columnProp('rowReorder')">
<component v-if="column.children && column.children.rowreordericon" :is="column.children.rowreordericon" :class="cx('rowReorderIcon')" />
<i v-else-if="columnProp('rowReorderIcon')" :class="[cx('rowReorderIcon'), columnProp('rowReorderIcon')]" />
<BarsIcon v-else :class="cx('rowReorderIcon')" data-pc-section="rowreordericon" />
<i v-else-if="columnProp('rowReorderIcon')" :class="[cx('rowReorderIcon'), columnProp('rowReorderIcon')]" v-bind="getColumnPT('rowReorderIcon')" />
<BarsIcon v-else :class="cx('rowReorderIcon')" v-bind="getColumnPT('rowReorderIcon')" />
</template>
<template v-else-if="columnProp('expander')">
<button v-ripple :class="cx('rowToggler')" type="button" :aria-expanded="isRowExpanded" :aria-controls="ariaControls" :aria-label="expandButtonAriaLabel" @click="toggleRow" v-bind="getColumnPT('rowToggler')">
@ -214,7 +214,9 @@ export default {
state: this.$data
},
context: {
index: this.index
index: this.index,
size: this.$parentInstance?.$parentInstance?.size,
showGridlines: this.$parentInstance?.$parentInstance?.showGridlines
}
};

View File

@ -14,11 +14,11 @@
:class="cx('filterMenuButton')"
@click="toggleMenu($event)"
@keydown="onToggleButtonKeyDown($event)"
v-bind="getColumnPT('filterMenuButton')"
v-bind="getColumnPT('filterMenuButton', ptmFilterMenuParams)"
>
<component :is="filterIconTemplate || 'FilterIcon'" />
<component :is="filterIconTemplate || 'FilterIcon'" v-bind="getColumnPT('filterMenuIcon')" />
</button>
<button v-if="showClearButton && display === 'row'" :class="cx('headerFilterClearButton')" type="button" @click="clearFilter()" v-bind="getColumnPT('headerFilterClearButton')">
<button v-if="showClearButton && display === 'row'" :class="cx('headerFilterClearButton')" type="button" @click="clearFilter()" v-bind="getColumnPT('headerFilterClearButton', ptmHeaderFilterClearParams)">
<component :is="filterClearIconTemplate || 'FilterSlashIcon'" v-bind="getColumnPT('filterClearIcon')" />
</button>
<Portal>
@ -47,7 +47,7 @@
@keydown="onRowMatchModeKeyDown($event)"
@keydown.enter.prevent="onRowMatchModeChange(matchMode.value)"
:tabindex="i === 0 ? '0' : null"
v-bind="getColumnPT('filterRowItem')"
v-bind="getColumnPT('filterRowItem', ptmFilterRowItemOptions(matchMode))"
>
{{ matchMode.label }}
</li>
@ -96,6 +96,9 @@
@click="removeConstraint(i)"
:label="removeRuleButtonLabel"
:unstyled="unstyled"
text
severity="danger"
size="small"
:pt="getColumnPT('filterRemoveButton')"
data-pc-section="filterremovebutton"
>
@ -114,6 +117,9 @@
:class="cx('filterAddRuleButton')"
@click="addConstraint()"
:unstyled="unstyled"
text
severity="info"
size="small"
:pt="getColumnPT('filterAddRuleButton')"
data-pc-section="filteraddrulebutton"
>
@ -130,6 +136,8 @@
:label="clearButtonLabel"
@click="clearFilter"
:unstyled="unstyled"
size="small"
outlined
:pt="getColumnPT('filterClearButton')"
data-pc-section="filterclearbutton"
></CFButton>
@ -142,6 +150,7 @@
:label="applyButtonLabel"
@click="applyFilter()"
:unstyled="unstyled"
size="small"
:pt="getColumnPT('filterApplyButton')"
data-pc-section="filterapplybutton"
></CFButton>
@ -169,6 +178,7 @@ import TrashIcon from 'primevue/icons/trash';
import OverlayEventBus from 'primevue/overlayeventbus';
import Portal from 'primevue/portal';
import { ConnectedOverlayScrollHandler, DomHandler, UniqueComponentId, ZIndexUtils } from 'primevue/utils';
import { mergeProps } from 'vue';
export default {
name: 'ColumnFilter',
@ -316,18 +326,28 @@ export default {
}
},
methods: {
getColumnPT(key) {
return this.ptmo(this.getColumnProp(), key, {
getColumnPT(key, params) {
const columnMetaData = {
props: this.column.props,
parent: {
props: this.$props,
state: this.$data
}
});
},
...params
};
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;
},
ptmFilterRowItemOptions(matchMode) {
return {
context: {
highlighted: matchMode && this.isRowMatchModeSelected(matchMode.value)
}
};
},
clearFilter() {
let _filters = { ...this.filters };
@ -667,6 +687,21 @@ export default {
},
filterConstraintAriaLabel() {
return this.$primevue.config.locale ? this.$primevue.config.locale.filterConstraint : undefined;
},
ptmHeaderFilterClearParams() {
return {
context: {
hidden: this.hasRowFilter()
}
};
},
ptmFilterMenuParams() {
return {
context: {
overlayVisible: this.overlayVisible,
active: this.hasFilter()
}
};
}
},
components: {

View File

@ -25,6 +25,7 @@ export interface DataTablePassThroughMethodOptions {
instance: any;
props: DataTableProps;
state: DataTableState;
context: DataTableContext;
}
/**
@ -721,6 +722,31 @@ export interface DataTableState {
d_editing: boolean;
}
/**
* Defines current options in DataTable component.
*/
export interface DataTableContext {
/**
* Current index of the row.
*/
index: number;
/**
* Current selectable state of row as a boolean.
* @defaultValue false
*/
selectable: boolean;
/**
* Current selected state of row as a boolean.
* @defaultValue false
*/
selected: boolean;
/**
* Current stripedRows state of row as a boolean.
* @defaultValue false
*/
stripedRows: boolean;
}
/**
* Defines valid properties in DataTable component.
*/
@ -1013,6 +1039,10 @@ export interface DataTableProps {
* @defaultValue false
*/
stripedRows?: boolean | undefined;
/**
* Defines the size of the table.
*/
size?: 'small' | 'large' | undefined;
/**
* Inline style of the table element.
*/

View File

@ -51,7 +51,9 @@ export default {
state: this.$data
},
context: {
index: this.index
index: this.index,
size: this.$parentInstance?.$parentInstance?.size,
showGridlines: this.$parentInstance?.$parentInstance?.showGridlines || false
}
};

View File

@ -27,7 +27,7 @@
<component v-if="column.children && column.children.header" :is="column.children.header" :column="column" />
<span v-if="columnProp('header')" :class="cx('headerTitle')" v-bind="getColumnPT('headerTitle')">{{ columnProp('header') }}</span>
<span v-if="columnProp('sortable')" v-bind="getColumnPT('sort')">
<component :is="(column.children && column.children.sorticon) || sortableColumnIcon" :sorted="sortState.sorted" :sortOrder="sortState.sortOrder" data-pc-section="sorticon" :class="cx('sortIcon')" />
<component :is="(column.children && column.children.sorticon) || sortableColumnIcon" :sorted="sortState.sorted" :sortOrder="sortState.sortOrder" data-pc-section="sorticon" :class="cx('sortIcon')" v-bind="getColumnPT('sorticon')" />
</span>
<span v-if="isMultiSorted()" :class="cx('sortBadge')" v-bind="getColumnPT('sortBadge')">{{ getBadgeValue() }}</span>
<DTHeaderCheckbox
@ -214,7 +214,11 @@ export default {
state: this.$data
},
context: {
index: this.index
index: this.index,
sorted: this.isColumnSorted(),
resizable: this.resizableColumns,
size: this.$parentInstance?.$parentInstance?.size,
showGridlines: this.$parentInstance?.$parentInstance?.showGridlines || false
}
};

View File

@ -24,6 +24,7 @@
import BaseComponent from 'primevue/basecomponent';
import CheckIcon from 'primevue/icons/check';
import { DomHandler } from 'primevue/utils';
import { mergeProps } from 'vue';
export default {
name: 'HeaderCheckbox',
@ -46,7 +47,7 @@ export default {
},
methods: {
getColumnPT(key) {
return this.ptmo(this.getColumnProp(), key, {
const columnMetaData = {
props: this.column.props,
parent: {
props: this.$props,
@ -57,7 +58,9 @@ export default {
focused: this.focused,
disabled: this.disabled
}
});
};
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:

View File

@ -25,6 +25,7 @@
import BaseComponent from 'primevue/basecomponent';
import CheckIcon from 'primevue/icons/check';
import { DomHandler } from 'primevue/utils';
import { mergeProps } from 'vue';
export default {
name: 'RowCheckbox',
@ -51,7 +52,7 @@ export default {
},
methods: {
getColumnPT(key) {
return this.ptmo(this.getColumnProp(), key, {
const columnMetaData = {
props: this.column.props,
parent: {
props: this.$props,
@ -63,7 +64,9 @@ export default {
focused: this.focused,
disabled: this.$attrs.disabled
}
});
};
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:

View File

@ -12,6 +12,7 @@
<script>
import BaseComponent from 'primevue/basecomponent';
import { DomHandler } from 'primevue/utils';
import { mergeProps } from 'vue';
export default {
name: 'RowRadioButton',
@ -36,7 +37,7 @@ export default {
},
methods: {
getColumnPT(key) {
return this.ptmo(this.getColumnProp(), key, {
const columnMetaData = {
props: this.column.props,
parent: {
props: this.$props,
@ -48,7 +49,9 @@ export default {
focused: this.focused,
disabled: this.$attrs.disabled
}
});
};
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:

View File

@ -1,5 +1,5 @@
<template>
<tbody :ref="bodyRef" :class="cx('tbody')" role="rowgroup" :style="bodyStyle" v-bind="ptm('tbody')">
<tbody :ref="bodyRef" :class="cx('tbody')" role="rowgroup" :style="bodyStyle" v-bind="ptm('tbody', ptmTBodyOptions)">
<template v-if="!empty">
<template v-for="(rowData, index) of value">
<tr
@ -10,14 +10,14 @@
role="row"
v-bind="ptm('rowGroupHeader')"
>
<td :colspan="columnsLength - 1" v-bind="{ ...getColumnPT('root'), ...getColumnPT('bodyCell') }">
<button v-if="expandableRowGroups" :class="cx('rowGroupToggler')" @click="onRowGroupToggle($event, rowData)" type="button" v-bind="getColumnPT('rowGroupToggler')">
<td :colspan="columnsLength - 1" v-bind="{ ...ptm('column.root'), ...ptm('column.bodyCell') }" data-pc-section="bodycell">
<button v-if="expandableRowGroups" :class="cx('rowGroupToggler')" @click="onRowGroupToggle($event, rowData)" type="button" v-bind="ptm('rowGroupToggler')">
<component v-if="templates['rowgrouptogglericon']" :is="templates['rowgrouptogglericon']" :expanded="isRowGroupExpanded(rowData)" />
<template v-else>
<span v-if="isRowGroupExpanded(rowData) && expandedRowIcon" :class="[cx('rowGroupTogglerIcon'), expandedRowIcon]" v-bind="getColumnPT('rowGroupTogglerIcon')" />
<ChevronDownIcon v-else-if="isRowGroupExpanded(rowData) && !expandedRowIcon" :class="cx('rowGroupTogglerIcon')" v-bind="getColumnPT('rowGroupTogglerIcon')" />
<span v-else-if="!isRowGroupExpanded(rowData) && collapsedRowIcon" :class="[cx('rowGroupTogglerIcon'), collapsedRowIcon]" v-bind="getColumnPT('rowGroupTogglerIcon')" />
<ChevronRightIcon v-else-if="!isRowGroupExpanded(rowData) && !collapsedRowIcon" :class="cx('rowGroupTogglerIcon')" v-bind="getColumnPT('rowGroupTogglerIcon')" />
<span v-if="isRowGroupExpanded(rowData) && expandedRowIcon" :class="[cx('rowGroupTogglerIcon'), expandedRowIcon]" v-bind="ptm('rowGroupTogglerIcon')" />
<ChevronDownIcon v-else-if="isRowGroupExpanded(rowData) && !expandedRowIcon" :class="cx('rowGroupTogglerIcon')" v-bind="ptm('rowGroupTogglerIcon')" />
<span v-else-if="!isRowGroupExpanded(rowData) && collapsedRowIcon" :class="[cx('rowGroupTogglerIcon'), collapsedRowIcon]" v-bind="ptm('rowGroupTogglerIcon')" />
<ChevronRightIcon v-else-if="!isRowGroupExpanded(rowData) && !collapsedRowIcon" :class="cx('rowGroupTogglerIcon')" v-bind="ptm('rowGroupTogglerIcon')" />
</template>
</button>
<component :is="templates['groupheader']" :data="rowData" :index="getRowIndex(index)" />
@ -42,7 +42,7 @@
@dragleave="onRowDragLeave($event)"
@dragend="onRowDragEnd($event)"
@drop="onRowDrop($event)"
v-bind="ptm('bodyRow')"
v-bind="getBodyRowPTOptions('bodyRow', rowData, index)"
:data-p-selectable-row="selectionMode ? true : false"
:data-p-highlight="selection && isSelected(rowData)"
:data-p-highlight-contextmenu="contextMenuSelection && isSelectedWithContextMenu(rowData)"
@ -102,7 +102,7 @@
role="row"
v-bind="ptm('rowGroupFooter')"
>
<td :colspan="columnsLength - 1" v-bind="{ ...getColumnPT('root'), ...getColumnPT('bodyCell') }">
<td :colspan="columnsLength - 1" v-bind="{ ...ptm('column.root'), ...ptm('column.footerCell') }" data-pc-section="footercell">
<component :is="templates['groupfooter']" :data="rowData" :index="getRowIndex(index)" />
</td>
</tr>
@ -121,6 +121,7 @@ import BaseComponent from 'primevue/basecomponent';
import ChevronDownIcon from 'primevue/icons/chevrondown';
import ChevronRightIcon from 'primevue/icons/chevronright';
import { DomHandler, ObjectUtils, UniqueComponentId } from 'primevue/utils';
import { mergeProps } from 'vue';
import BodyCell from './BodyCell.vue';
export default {
@ -306,18 +307,30 @@ export default {
columnProp(col, prop) {
return ObjectUtils.getVNodeProp(col, prop);
},
getColumnPT(column, key) {
return this.ptmo(this.getColumnProp(column), key, {
props: column.props,
getColumnPT(currentColumn, key) {
const columnMetaData = {
props: currentColumn.props,
parent: {
props: this.$props,
state: this.$data
}
});
};
return mergeProps(this.ptm(`column.${key}`, { column: columnMetaData }), this.ptm(`column.${key}`, columnMetaData), this.ptmo(this.getColumnProp(currentColumn), key, columnMetaData));
},
getColumnProp(column) {
return column.props && column.props.pt ? column.props.pt : undefined; //@todo
},
getBodyRowPTOptions(key, rowdata, index) {
return this.ptm(key, {
context: {
index,
selectable: this.$parentInstance?.$parentInstance?.rowHover || this.$parentInstance?.$parentInstance?.selectionMode,
selected: this.isSelected(rowdata),
stripedRows: this.$parentInstance?.$parentInstance?.stripedRows || false
}
});
},
shouldRenderRowGroupHeader(value, rowData, i) {
let currentRowFieldData = ObjectUtils.resolveFieldData(rowData, this.groupRowsBy);
let prevRowData = value[i - 1];
@ -609,6 +622,13 @@ export default {
},
nameAttributeSelector() {
return UniqueComponentId();
},
ptmTBodyOptions() {
return {
context: {
scrollable: this.$parentInstance?.$parentInstance?.scrollable
}
};
}
},
components: {

View File

@ -1,5 +1,5 @@
<template>
<tfoot v-if="hasFooter" :class="cx('tfoot')" :style="sx('tfoot')" role="rowgroup" v-bind="columnGroup ? { ...ptm('tfoot'), ...getColumnGroupPT('root') } : ptm('tfoot')" data-pc-section="tfoot">
<tfoot v-if="hasFooter" :class="cx('tfoot')" :style="sx('tfoot')" role="rowgroup" v-bind="columnGroup ? { ...ptm('tfoot', ptmTFootOptions), ...getColumnGroupPT('root') } : ptm('tfoot', ptmTFootOptions)" data-pc-section="tfoot">
<tr v-if="!columnGroup" role="row" v-bind="ptm('footerRow')">
<template v-for="(col, i) of columns" :key="columnProp(col, 'columnKey') || columnProp(col, 'field') || i">
<DTFooterCell v-if="!columnProp(col, 'hidden')" :column="col" :pt="pt" />
@ -47,7 +47,8 @@ export default {
state: this.$data
},
context: {
type: 'header'
type: 'footer',
scrollable: this.ptmTFootOptions.context.scrollable
}
};
@ -119,6 +120,13 @@ export default {
}
return hasFooter;
},
ptmTFootOptions() {
return {
context: {
scrollable: this.$parentInstance?.$parentInstance?.scrollable
}
};
}
},
components: {

View File

@ -1,5 +1,5 @@
<template>
<thead :class="cx('thead')" :style="sx('thead')" role="rowgroup" v-bind="columnGroup ? { ...ptm('thead'), ...getColumnGroupPT('root') } : ptm('thead')" data-pc-section="thead">
<thead :class="cx('thead')" :style="sx('thead')" role="rowgroup" v-bind="columnGroup ? { ...ptm('thead', ptmTHeadOptions), ...getColumnGroupPT('root') } : ptm('thead', ptmTHeadOptions)" data-pc-section="thead">
<template v-if="!columnGroup">
<tr role="row" v-bind="ptm('headerRow')">
<template v-for="(col, i) of columns" :key="columnProp(col, 'columnKey') || columnProp(col, 'field') || i">
@ -244,7 +244,8 @@ export default {
state: this.$data
},
context: {
type: 'header'
type: 'header',
scrollable: this.$parentInstance?.$parentInstance?.scrollable
}
};
@ -323,6 +324,15 @@ export default {
}
}
},
computed: {
ptmTHeadOptions() {
return {
context: {
scrollable: this.$parentInstance?.$parentInstance?.scrollable
}
};
}
},
components: {
DTHeaderCell: HeaderCell,
DTHeaderCheckbox: HeaderCheckbox,