Skip to content

Commit d79493c

Browse files
committed
add row grouping based on column on datagrid
1 parent 4218d71 commit d79493c

File tree

2 files changed

+97
-52
lines changed

2 files changed

+97
-52
lines changed

src/components/compounds/Table/DataGrid.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,17 @@ class DataGrid {
155155
return obj;
156156
} , {})
157157
}
158+
159+
groups(column) {
160+
return this.rows.reduce((set, row) => {
161+
set.add(row[column])
162+
return set;
163+
}, new Set())
164+
}
165+
166+
filterRows(column, value) {
167+
return this.rows.filter(row => row[column] === value)
168+
}
158169
}
159170

160171
export default DataGrid

src/components/compounds/Table/Table.vue

Lines changed: 86 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ const Table = {
3232
expandable: Boolean,
3333
draggableRows: Boolean,
3434
draggableColumns: Boolean,
35-
editable: Boolean
35+
editable: Boolean,
36+
groupBy: String,
3637
},
3738
3839
setup(props, { emit }) {
@@ -42,7 +43,8 @@ const Table = {
4243
const rowsPerPage = ref(props.rowsPerPage)
4344
const currentPage = ref(0)
4445
const search = reactive({})
45-
const expanded = ref(new Set())
46+
const expandedRows = ref(new Set())
47+
const expandedGroups = ref(new Set())
4648
4749
// whenever pagination props changes, update the class state accordingly
4850
// thsi way pagination settings are directly passed to props and indirectly passed to class
@@ -72,11 +74,19 @@ const Table = {
7274
}
7375
7476
const toggleExpanded = rowId => {
75-
if (expanded.value.has(rowId)) {
76-
expanded.value.delete(rowId)
77+
if (expandedRows.value.has(rowId)) {
78+
expandedRows.value.delete(rowId)
7779
return
7880
}
79-
expanded.value.add(rowId)
81+
expandedRows.value.add(rowId)
82+
}
83+
84+
const toggleExpandedGroup = group => {
85+
if (expandedGroups.value.has(group)) {
86+
expandedGroups.value.delete(group)
87+
return
88+
}
89+
expandedGroups.value.add(group)
8090
}
8191
8292
const rootClasses = computed(() => {
@@ -92,16 +102,11 @@ const Table = {
92102
})
93103
94104
const countColumns = computed(() => {
95-
return (
96-
data.value.getColumns().length +
97-
(props.checkable ? 1 : 0) +
98-
(props.expandable ? 1 : 0)
99-
)
105+
return data.value.getColumns().length + (props.checkable ? 1 : 0) + (props.expandable ? 1 : 0)
100106
})
101107
102108
const handleBackPage = () => {
103-
if (currentPage.value > 0)
104-
currentPage.value -= 1
109+
if (currentPage.value > 0) currentPage.value -= 1
105110
}
106111
107112
const handleNextPage = () => {
@@ -117,11 +122,13 @@ const Table = {
117122
rowsPerPage,
118123
currentPage,
119124
rootClasses,
120-
expanded,
125+
expandedRows,
121126
toggleExpanded,
127+
expandedGroups,
128+
toggleExpandedGroup,
122129
countColumns,
123130
handleBackPage,
124-
handleNextPage
131+
handleNextPage,
125132
}
126133
},
127134
}
@@ -180,43 +187,74 @@ export default Table
180187
/>
181188
</td>
182189
</tr>
183-
<template v-for="(row, idx) in data.rows" :key="idx">
184-
<tr
185-
:draggable="draggableRows"
186-
@dragstart="data.onDragStartRow($event, row, idx)"
187-
@drop="data.onDropRow($event, row, idx)"
188-
@dragover="data.onDragOverRow($event, row, idx)"
189-
@dragleave="data.onDragLeaveRow($event, row, idx)"
190-
:class="{ 'has-background-primary': row.selected, 'has-text-white': row.selected }"
191-
>
192-
<td v-if="checkable">
193-
<v-checkbox @change="data.toggleCheck($event, row)" />
194-
</td>
195-
<td v-if="expandable">
196-
<a
197-
><v-tag @click="toggleExpanded(row.id)" type="is-primary">{{
198-
expanded.has(row.id) ? '&uarr;' : '&darr;'
199-
}}</v-tag></a
190+
<template v-if="!groupBy">
191+
<template v-for="(row, idx) in data.rows" :key="idx">
192+
<tr
193+
:draggable="draggableRows"
194+
@dragstart="data.onDragStartRow($event, row, idx)"
195+
@drop="data.onDropRow($event, row, idx)"
196+
@dragover="data.onDragOverRow($event, row, idx)"
197+
@dragleave="data.onDragLeaveRow($event, row, idx)"
198+
:class="{ 'has-background-primary': row.selected, 'has-text-white': row.selected }"
199+
>
200+
<td v-if="checkable">
201+
<v-checkbox @change="data.toggleCheck($event, row)" />
202+
</td>
203+
<td v-if="expandable">
204+
<a @click="toggleExpanded(row.id)" class="is-primary">{{
205+
expandedRows.has(row.id) ? '&uarr;' : '&darr;'
206+
}}</a>
207+
</td>
208+
<td
209+
v-for="column in data.getColumns()"
210+
:key="column.name"
211+
:class="column.style"
212+
:contenteditable="props.editable"
213+
v-on:blur="data.editCell(row, column, $event.target.textContent)"
200214
>
201-
</td>
202-
<td
203-
v-for="column in data.getColumns()"
204-
:key="column.name" :class="column.style"
205-
:contenteditable='props.editable'
206-
v-on:blur="data.editCell(row, column, $event.target.textContent)">
207-
<slot :name="column.name" :row="row">
208-
{{ row[column.name] }}
209-
</slot>
210-
</td>
211-
</tr>
212-
<tr class="expansion" v-if="expanded.has(row.id)">
213-
<td :colspan="countColumns">
214-
<slot name="expanded" :row="row" />
215-
</td>
216-
</tr>
215+
<slot :name="column.name" :row="row">
216+
{{ row[column.name] }}
217+
</slot>
218+
</td>
219+
</tr>
220+
<tr class="expansion" v-if="expandedRows.has(row.id)">
221+
<td :colspan="countColumns">
222+
<slot name="expanded" :row="row" />
223+
</td>
224+
</tr>
225+
</template>
226+
</template>
227+
228+
<template v-if="groupBy">
229+
<template v-for="(group, idx) in data.groups(groupBy)" :key="idx">
230+
<tr>
231+
<td :colspan="countColumns">
232+
<a @click="toggleExpandedGroup(group)" class="mr-4">{{
233+
expandedGroups.has(group) ? '&darr;' : '&rarr;'
234+
}}</a>
235+
{{ groupBy }}: <v-tag type="is-primary" class="mx-4">{{ group }} </v-tag>
236+
</td>
237+
</tr>
238+
<template v-if="expandedGroups.has(group)">
239+
<tr v-for="(row, idx) in data.filterRows(groupBy, group)" :key="idx">
240+
<td
241+
v-for="column in data.getColumns()"
242+
:key="column.name"
243+
:class="column.style"
244+
:contenteditable="props.editable"
245+
v-on:blur="data.editCell(row, column, $event.target.textContent)"
246+
>
247+
<slot :name="column.name" :row="row">
248+
{{ row[column.name] }}
249+
</slot>
250+
</td>
251+
</tr>
252+
</template>
253+
</template>
217254
</template>
218255
</tbody>
219256
</table>
257+
220258
<!-- todo: move the styles to their own scope -->
221259
<div
222260
class="pagination-wrapper"
@@ -231,11 +269,7 @@ export default Table
231269
</v-select>
232270
<!-- using :disabled wont work, so instead the click action is conditioned and the buttons are always clickable -->
233271
<a class="pagination-previous" @click="handleBackPage">Previous</a>
234-
<a
235-
class="pagination-next"
236-
@click="handleNextPage"
237-
>Next page</a
238-
>
272+
<a class="pagination-next" @click="handleNextPage">Next page</a>
239273
</div>
240274

241275
<div class="tableFooter">

0 commit comments

Comments
 (0)