Implemented expandable row groups

pull/104/head
cagataycivici 2019-10-21 17:20:06 +03:00
parent 6791638015
commit b10c4eda66
2 changed files with 128 additions and 16 deletions

View File

@ -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) {

View File

@ -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>
&lt;h3&gt;Subheader Grouping&lt;/h3&gt;
&lt;DataTable :value="cars" rowGroupMode="subheader" groupRowsBy="brand"
sortMode="single" sortField="brand" :sortOrder="1"&gt;
&lt;Column field="brand" header="Brand"&gt;&lt;/Column&gt;
&lt;Column field="vin" header="Vin"&gt;&lt;/Column&gt;
&lt;Column field="year" header="Year"&gt;&lt;/Column&gt;
&lt;Column field="color" header="Color"&gt;&lt;/Column&gt;
&lt;Column field="price" header="Price"&gt;&lt;/Column&gt;
&lt;template #groupheader="slotProps"&gt;
&lt;span&gt;&#123;&#123;slotProps.data.brand&#125;&#125;&lt;/span&gt;
&lt;/template&gt;
&lt;template #groupfooter="slotProps"&gt;
&lt;td colspan="3" style="text-align: right"&gt;Total Price&lt;/td&gt;
&lt;td&gt;20000&lt;/td&gt;
&lt;/template&gt;
&lt;/DataTable&gt;
&lt;h3&gt;Expandable Row Groups&lt;/h3&gt;
&lt;DataTable :value="cars" rowGroupMode="subheader" groupRowsBy="brand"
sortMode="single" sortField="brand" :sortOrder="1"
:expandableRowGroups="true" :expandedRowGroups.sync="expandedRowGroups"&gt;
&lt;Column field="brand" header="Brand"&gt;&lt;/Column&gt;
&lt;Column field="vin" header="Vin"&gt;&lt;/Column&gt;
&lt;Column field="year" header="Year"&gt;&lt;/Column&gt;
&lt;Column field="color" header="Color"&gt;&lt;/Column&gt;
&lt;Column field="price" header="Price"&gt;&lt;/Column&gt;
&lt;template #groupheader="slotProps"&gt;
&lt;span&gt;&#123;&#123;slotProps.data.brand&#125;&#125;&lt;/span&gt;
&lt;/template&gt;
&lt;template #groupfooter="slotProps"&gt;
&lt;td colspan="3" style="text-align: right"&gt;Total Price&lt;/td&gt;
&lt;td&gt;20000&lt;/td&gt;
&lt;/template&gt;
&lt;/DataTable&gt;
&lt;h3&gt;RowSpan Grouping&lt;/h3&gt;
&lt;DataTable :value="cars" rowGroupMode="rowspan" groupRowsBy="brand"
sortMode="single" sortField="brand" :sortOrder="1"&gt;
&lt;Column header="#" headerStyle="width:3em"&gt;
&lt;template #body="slotProps"&gt;
&#123;&#123;slotProps.index&#125;&#125;
&lt;/template&gt;
&lt;/Column&gt;
&lt;Column field="brand" header="Brand"&gt;&lt;/Column&gt;
&lt;Column field="year" header="Year"&gt;&lt;/Column&gt;
&lt;Column field="vin" header="Vin"&gt;&lt;/Column&gt;
&lt;Column field="color" header="Color"&gt;&lt;/Column&gt;
&lt;Column field="price" header="Price"&gt;&lt;/Column&gt;
&lt;/DataTable&gt;
</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>