Implemented expandable row groups
parent
6791638015
commit
b10c4eda66
|
@ -57,10 +57,14 @@
|
||||||
<template v-for="(rowData, index) of dataToRender">
|
<template v-for="(rowData, index) of dataToRender">
|
||||||
<tr class="p-rowgroup-header" v-if="rowGroupMode === 'subheader' && shouldRenderRowGroupHeader(dataToRender, rowData, index)" :key="getRowKey(rowData, index) + '_subheader'">
|
<tr class="p-rowgroup-header" v-if="rowGroupMode === 'subheader' && shouldRenderRowGroupHeader(dataToRender, rowData, index)" :key="getRowKey(rowData, index) + '_subheader'">
|
||||||
<td :colspan="columns.length - 1">
|
<td :colspan="columns.length - 1">
|
||||||
|
<button class="p-row-toggler p-link" @click="toggleRowGroup($event, rowData)" v-if="expandableRowGroups">
|
||||||
|
<span :class="rowGroupTogglerIcon(rowData)"></span>
|
||||||
|
</button>
|
||||||
<slot name="groupheader" :data="rowData"></slot>
|
<slot name="groupheader" :data="rowData"></slot>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr :class="getRowClass(rowData)" :key="getRowKey(rowData, index)"
|
<tr :class="getRowClass(rowData)" :key="getRowKey(rowData, index)"
|
||||||
|
v-if="expandableRowGroups ? isRowGroupExpanded(rowData): true"
|
||||||
@click="onRowClick($event, rowData, index)" @touchend="onRowTouchEnd($event)" @keydown="onRowKeyDown($event, rowData, index)" :tabindex="selectionMode ? '0' : null"
|
@click="onRowClick($event, rowData, index)" @touchend="onRowTouchEnd($event)" @keydown="onRowKeyDown($event, rowData, index)" :tabindex="selectionMode ? '0' : null"
|
||||||
@mousedown="onRowMouseDown($event)" @dragstart="onRowDragStart($event, index)" @dragover="onRowDragOver($event,index)" @dragleave="onRowDragLeave($event)" @dragend="onRowDragEnd($event)" @drop="onRowDrop($event)">
|
@mousedown="onRowMouseDown($event)" @dragstart="onRowDragStart($event, index)" @dragover="onRowDragOver($event,index)" @dragleave="onRowDragLeave($event)" @dragend="onRowDragEnd($event)" @drop="onRowDrop($event)">
|
||||||
<template v-for="(col,i) of columns">
|
<template v-for="(col,i) of columns">
|
||||||
|
@ -283,6 +287,14 @@ export default {
|
||||||
groupRowsBy: {
|
groupRowsBy: {
|
||||||
type: [Array,String],
|
type: [Array,String],
|
||||||
default: null
|
default: null
|
||||||
|
},
|
||||||
|
expandableRowGroups: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
expandedRowGroups: {
|
||||||
|
type: Array,
|
||||||
|
default: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
@ -823,6 +835,10 @@ export default {
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
isRowGroupExpanded(rowData) {
|
||||||
|
let groupFieldValue = ObjectUtils.resolveFieldData(rowData, this.groupRowsBy);
|
||||||
|
return this.expandableRowGroups && this.expandedRowGroups && this.expandedRowGroups.indexOf(groupFieldValue) > -1;
|
||||||
|
},
|
||||||
getRowKey(rowData, index) {
|
getRowKey(rowData, index) {
|
||||||
return this.dataKey ? ObjectUtils.resolveFieldData(rowData, this.dataKey): index;
|
return this.dataKey ? ObjectUtils.resolveFieldData(rowData, this.dataKey): index;
|
||||||
},
|
},
|
||||||
|
@ -1240,10 +1256,29 @@ export default {
|
||||||
this.$emit('row-expand', event);
|
this.$emit('row-expand', event);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
toggleRowGroup(event, data) {
|
||||||
|
let groupFieldValue = ObjectUtils.resolveFieldData(data, this.groupRowsBy);
|
||||||
|
let _expandedRowGroups = this.expandedRowGroups ? [...this.expandedRowGroups] : [];
|
||||||
|
|
||||||
|
if (this.isRowGroupExpanded(data)) {
|
||||||
|
_expandedRowGroups = _expandedRowGroups.filter(group => group !== groupFieldValue);
|
||||||
|
this.$emit('update:expandedRowGroups', _expandedRowGroups);
|
||||||
|
this.$emit('rowgroup-collapse', {originalEvent: event, data: groupFieldValue});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_expandedRowGroups.push(groupFieldValue);
|
||||||
|
this.$emit('update:expandedRowGroups', _expandedRowGroups);
|
||||||
|
this.$emit('rowgroup-expand', {originalEvent: event, data: groupFieldValue});
|
||||||
|
}
|
||||||
|
},
|
||||||
rowTogglerIcon(rowData) {
|
rowTogglerIcon(rowData) {
|
||||||
const icon = this.isRowExpanded(rowData) ? this.expandedRowIcon : this.collapsedRowIcon;
|
const icon = this.isRowExpanded(rowData) ? this.expandedRowIcon : this.collapsedRowIcon;
|
||||||
return ['p-row-toggler-icon pi pi-fw p-clickable', icon];
|
return ['p-row-toggler-icon pi pi-fw p-clickable', icon];
|
||||||
},
|
},
|
||||||
|
rowGroupTogglerIcon(rowData) {
|
||||||
|
const icon = this.isRowGroupExpanded(rowData) ? this.expandedRowIcon : this.collapsedRowIcon;
|
||||||
|
return ['p-row-toggler-icon pi pi-fw p-clickable', icon];
|
||||||
|
},
|
||||||
shouldRenderRowGroupHeader(value, rowData, i) {
|
shouldRenderRowGroupHeader(value, rowData, i) {
|
||||||
let currentRowFieldData = ObjectUtils.resolveFieldData(rowData, this.groupRowsBy);
|
let currentRowFieldData = ObjectUtils.resolveFieldData(rowData, this.groupRowsBy);
|
||||||
let prevRowData = value[i - 1];
|
let prevRowData = value[i - 1];
|
||||||
|
@ -1256,14 +1291,19 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
shouldRenderRowGroupFooter(value, rowData, i) {
|
shouldRenderRowGroupFooter(value, rowData, i) {
|
||||||
let currentRowFieldData = ObjectUtils.resolveFieldData(rowData, this.groupRowsBy);
|
if (this.expandableRowGroups && !this.isRowGroupExpanded(rowData)) {
|
||||||
let nextRowData = value[i + 1];
|
return false;
|
||||||
if (nextRowData) {
|
|
||||||
let nextRowFieldData = ObjectUtils.resolveFieldData(nextRowData, this.groupRowsBy);
|
|
||||||
return currentRowFieldData !== nextRowFieldData;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return true;
|
let currentRowFieldData = ObjectUtils.resolveFieldData(rowData, this.groupRowsBy);
|
||||||
|
let nextRowData = value[i + 1];
|
||||||
|
if (nextRowData) {
|
||||||
|
let nextRowFieldData = ObjectUtils.resolveFieldData(nextRowData, this.groupRowsBy);
|
||||||
|
return currentRowFieldData !== nextRowFieldData;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
shouldRenderBodyCell(value, column, i) {
|
shouldRenderBodyCell(value, column, i) {
|
||||||
|
|
|
@ -29,7 +29,8 @@
|
||||||
|
|
||||||
<h3>Expandable Row Groups</h3>
|
<h3>Expandable Row Groups</h3>
|
||||||
<DataTable :value="cars" rowGroupMode="subheader" groupRowsBy="brand"
|
<DataTable :value="cars" rowGroupMode="subheader" groupRowsBy="brand"
|
||||||
sortMode="single" sortField="brand" :sortOrder="1">
|
sortMode="single" sortField="brand" :sortOrder="1"
|
||||||
|
:expandableRowGroups="true" :expandedRowGroups.sync="expandedRowGroups">
|
||||||
<Column field="brand" header="Brand"></Column>
|
<Column field="brand" header="Brand"></Column>
|
||||||
<Column field="vin" header="Vin"></Column>
|
<Column field="vin" header="Vin"></Column>
|
||||||
<Column field="year" header="Year"></Column>
|
<Column field="year" header="Year"></Column>
|
||||||
|
@ -46,7 +47,7 @@
|
||||||
|
|
||||||
<h3>RowSpan Grouping</h3>
|
<h3>RowSpan Grouping</h3>
|
||||||
<DataTable :value="cars" rowGroupMode="rowspan" groupRowsBy="brand"
|
<DataTable :value="cars" rowGroupMode="rowspan" groupRowsBy="brand"
|
||||||
sortMode="multiple" :multiSortMeta="multiSortMeta">
|
sortMode="single" sortField="brand" :sortOrder="1">
|
||||||
<Column header="#" headerStyle="width:3em">
|
<Column header="#" headerStyle="width:3em">
|
||||||
<template #body="slotProps">
|
<template #body="slotProps">
|
||||||
{{slotProps.index}}
|
{{slotProps.index}}
|
||||||
|
@ -65,12 +66,76 @@
|
||||||
<TabPanel header="Source">
|
<TabPanel header="Source">
|
||||||
<CodeHighlight>
|
<CodeHighlight>
|
||||||
<template v-pre>
|
<template v-pre>
|
||||||
|
<h3>Subheader Grouping</h3>
|
||||||
|
<DataTable :value="cars" rowGroupMode="subheader" groupRowsBy="brand"
|
||||||
|
sortMode="single" sortField="brand" :sortOrder="1">
|
||||||
|
<Column field="brand" header="Brand"></Column>
|
||||||
|
<Column field="vin" header="Vin"></Column>
|
||||||
|
<Column field="year" header="Year"></Column>
|
||||||
|
<Column field="color" header="Color"></Column>
|
||||||
|
<Column field="price" header="Price"></Column>
|
||||||
|
<template #groupheader="slotProps">
|
||||||
|
<span>{{slotProps.data.brand}}</span>
|
||||||
|
</template>
|
||||||
|
<template #groupfooter="slotProps">
|
||||||
|
<td colspan="3" style="text-align: right">Total Price</td>
|
||||||
|
<td>20000</td>
|
||||||
|
</template>
|
||||||
|
</DataTable>
|
||||||
|
|
||||||
|
<h3>Expandable Row Groups</h3>
|
||||||
|
<DataTable :value="cars" rowGroupMode="subheader" groupRowsBy="brand"
|
||||||
|
sortMode="single" sortField="brand" :sortOrder="1"
|
||||||
|
:expandableRowGroups="true" :expandedRowGroups.sync="expandedRowGroups">
|
||||||
|
<Column field="brand" header="Brand"></Column>
|
||||||
|
<Column field="vin" header="Vin"></Column>
|
||||||
|
<Column field="year" header="Year"></Column>
|
||||||
|
<Column field="color" header="Color"></Column>
|
||||||
|
<Column field="price" header="Price"></Column>
|
||||||
|
<template #groupheader="slotProps">
|
||||||
|
<span>{{slotProps.data.brand}}</span>
|
||||||
|
</template>
|
||||||
|
<template #groupfooter="slotProps">
|
||||||
|
<td colspan="3" style="text-align: right">Total Price</td>
|
||||||
|
<td>20000</td>
|
||||||
|
</template>
|
||||||
|
</DataTable>
|
||||||
|
|
||||||
|
<h3>RowSpan Grouping</h3>
|
||||||
|
<DataTable :value="cars" rowGroupMode="rowspan" groupRowsBy="brand"
|
||||||
|
sortMode="single" sortField="brand" :sortOrder="1">
|
||||||
|
<Column header="#" headerStyle="width:3em">
|
||||||
|
<template #body="slotProps">
|
||||||
|
{{slotProps.index}}
|
||||||
|
</template>
|
||||||
|
</Column>
|
||||||
|
<Column field="brand" header="Brand"></Column>
|
||||||
|
<Column field="year" header="Year"></Column>
|
||||||
|
<Column field="vin" header="Vin"></Column>
|
||||||
|
<Column field="color" header="Color"></Column>
|
||||||
|
<Column field="price" header="Price"></Column>
|
||||||
|
</DataTable>
|
||||||
</template>
|
</template>
|
||||||
</CodeHighlight>
|
</CodeHighlight>
|
||||||
|
|
||||||
<CodeHighlight lang="javascript">
|
<CodeHighlight lang="javascript">
|
||||||
|
import CarService from '../../service/CarService';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
cars: null,
|
||||||
|
expandedRowGroups: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
carService: null,
|
||||||
|
created() {
|
||||||
|
this.carService = new CarService();
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.carService.getCarsMedium().then(data => this.cars = data);
|
||||||
|
}
|
||||||
|
}
|
||||||
</CodeHighlight>
|
</CodeHighlight>
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
</TabView>
|
</TabView>
|
||||||
|
@ -86,17 +151,12 @@ export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
cars: null,
|
cars: null,
|
||||||
multiSortMeta: null
|
expandedRowGroups: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
carService: null,
|
carService: null,
|
||||||
created() {
|
created() {
|
||||||
this.carService = new CarService();
|
this.carService = new CarService();
|
||||||
|
|
||||||
this.multiSortMeta = [
|
|
||||||
{field: 'brand', order: 1},
|
|
||||||
{field: 'year', order: 1}
|
|
||||||
];
|
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.carService.getCarsMedium().then(data => this.cars = data);
|
this.carService.getCarsMedium().then(data => this.cars = data);
|
||||||
|
@ -108,8 +168,20 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.p-rowgroup-header span,
|
|
||||||
.p-rowgroup-footer td {
|
.p-rowgroup-footer td {
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
::v-deep .p-rowgroup-header {
|
||||||
|
span {
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-row-toggler {
|
||||||
|
vertical-align: middle;
|
||||||
|
margin-right: .25em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
</style>
|
</style>
|
Loading…
Reference in New Issue