Implemented expandable row groups
parent
6791638015
commit
b10c4eda66
|
@ -57,10 +57,14 @@
|
|||
<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'">
|
||||
<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>
|
||||
</td>
|
||||
</tr>
|
||||
<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"
|
||||
@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">
|
||||
|
@ -283,6 +287,14 @@ export default {
|
|||
groupRowsBy: {
|
||||
type: [Array,String],
|
||||
default: null
|
||||
},
|
||||
expandableRowGroups: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
expandedRowGroups: {
|
||||
type: Array,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
data() {
|
||||
|
@ -823,6 +835,10 @@ export default {
|
|||
|
||||
return false;
|
||||
},
|
||||
isRowGroupExpanded(rowData) {
|
||||
let groupFieldValue = ObjectUtils.resolveFieldData(rowData, this.groupRowsBy);
|
||||
return this.expandableRowGroups && this.expandedRowGroups && this.expandedRowGroups.indexOf(groupFieldValue) > -1;
|
||||
},
|
||||
getRowKey(rowData, index) {
|
||||
return this.dataKey ? ObjectUtils.resolveFieldData(rowData, this.dataKey): index;
|
||||
},
|
||||
|
@ -1240,10 +1256,29 @@ export default {
|
|||
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) {
|
||||
const icon = this.isRowExpanded(rowData) ? this.expandedRowIcon : this.collapsedRowIcon;
|
||||
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) {
|
||||
let currentRowFieldData = ObjectUtils.resolveFieldData(rowData, this.groupRowsBy);
|
||||
let prevRowData = value[i - 1];
|
||||
|
@ -1256,14 +1291,19 @@ export default {
|
|||
}
|
||||
},
|
||||
shouldRenderRowGroupFooter(value, rowData, i) {
|
||||
let currentRowFieldData = ObjectUtils.resolveFieldData(rowData, this.groupRowsBy);
|
||||
let nextRowData = value[i + 1];
|
||||
if (nextRowData) {
|
||||
let nextRowFieldData = ObjectUtils.resolveFieldData(nextRowData, this.groupRowsBy);
|
||||
return currentRowFieldData !== nextRowFieldData;
|
||||
if (this.expandableRowGroups && !this.isRowGroupExpanded(rowData)) {
|
||||
return false;
|
||||
}
|
||||
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) {
|
||||
|
|
|
@ -29,7 +29,8 @@
|
|||
|
||||
<h3>Expandable Row Groups</h3>
|
||||
<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="vin" header="Vin"></Column>
|
||||
<Column field="year" header="Year"></Column>
|
||||
|
@ -46,7 +47,7 @@
|
|||
|
||||
<h3>RowSpan Grouping</h3>
|
||||
<DataTable :value="cars" rowGroupMode="rowspan" groupRowsBy="brand"
|
||||
sortMode="multiple" :multiSortMeta="multiSortMeta">
|
||||
sortMode="single" sortField="brand" :sortOrder="1">
|
||||
<Column header="#" headerStyle="width:3em">
|
||||
<template #body="slotProps">
|
||||
{{slotProps.index}}
|
||||
|
@ -65,12 +66,76 @@
|
|||
<TabPanel header="Source">
|
||||
<CodeHighlight>
|
||||
<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>
|
||||
</CodeHighlight>
|
||||
|
||||
<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>
|
||||
</TabPanel>
|
||||
</TabView>
|
||||
|
@ -86,17 +151,12 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
cars: null,
|
||||
multiSortMeta: null
|
||||
expandedRowGroups: null
|
||||
}
|
||||
},
|
||||
carService: null,
|
||||
created() {
|
||||
this.carService = new CarService();
|
||||
|
||||
this.multiSortMeta = [
|
||||
{field: 'brand', order: 1},
|
||||
{field: 'year', order: 1}
|
||||
];
|
||||
},
|
||||
mounted() {
|
||||
this.carService.getCarsMedium().then(data => this.cars = data);
|
||||
|
@ -108,8 +168,20 @@ export default {
|
|||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.p-rowgroup-header span,
|
||||
.p-rowgroup-footer td {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
::v-deep .p-rowgroup-header {
|
||||
span {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.p-row-toggler {
|
||||
vertical-align: middle;
|
||||
margin-right: .25em;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</style>
|
Loading…
Reference in New Issue