Skip to content

Commit 354633a

Browse files
committed
feat+refactor(QTable): Improve slots scoped data; Add "header-selection" and "body-selection" scoped slots quasarframework#7519
1 parent ea43289 commit 354633a

17 files changed

+1166
-580
lines changed
Lines changed: 57 additions & 175 deletions
Original file line numberDiff line numberDiff line change
@@ -1,127 +1,56 @@
11
<template>
2-
<div class="q-layout-padding">
3-
<q-input filled v-model="filter" label="Search" debounce="300">
4-
<q-icon slot="append" name="search" />
5-
</q-input>
6-
7-
<div>
8-
<q-toggle color="primary" v-model="loading" label="Show loading" />
9-
<q-toggle color="primary" v-model="dense" label="Dense" />
10-
<q-select filled multiple v-model="visibleColumns" :options="columns" option-value="name" option-disable="required" emit-value />
11-
<q-select class="q-mt-md" filled v-model="separator" :options="['horizontal', 'vertical', 'cell', 'none']" />
2+
<div class="q-pa-md">
3+
<div class="row items-center q-gutter-sm q-mb-md">
4+
<q-btn label="Toggle data / no data" no-caps color="primary" @click="toggleData" />
5+
<q-toggle label="Hide bottom" v-model="hideBottom" />
6+
<q-toggle label="Hide sel rows banner" v-model="hideSelectedBanner" />
7+
<q-toggle label="Hide no data" v-model="hideNoData" />
8+
<q-toggle label="Hide pagination" v-model="hidePagination" />
129
</div>
1310

14-
<h2>Fixed header</h2>
15-
<q-table
16-
:dense="dense"
17-
table-style="max-height: 500px"
18-
class="table-sticky"
19-
:separator="separator"
20-
:data="data"
21-
:columns="columns"
22-
:title="title"
23-
:filter="filter"
24-
:loading="loading"
25-
:visible-columns="visibleColumns"
26-
row-key="index"
27-
virtual-scroll
28-
:virtual-scroll-sticky-start="dense ? 24 : 48"
29-
:pagination.sync="pagination"
30-
:rows-per-page-options="[0]"
31-
/>
32-
33-
<h2>Basic</h2>
34-
<q-table
35-
:dense="dense"
36-
table-style="max-height: 500px"
37-
:separator="separator"
38-
:data="data"
39-
:columns="columns"
40-
:title="title"
41-
:filter="filter"
42-
:loading="loading"
43-
:visible-columns="visibleColumns"
44-
row-key="index"
45-
virtual-scroll
46-
/>
47-
48-
<h2>With slots</h2>
4911
<q-table
50-
ref="virtualScrollTable"
51-
:dense="dense"
52-
table-style="max-height: 500px"
53-
class="table-sticky"
54-
:separator="separator"
55-
:data="data"
12+
title="Treats"
13+
:data="rows"
5614
:columns="columns"
57-
:title="title"
58-
:filter="filter"
59-
:loading="loading"
60-
:visible-columns="visibleColumns"
61-
row-key="index"
62-
:virtual-scroll="pagination.rowsPerPage === 0"
63-
:virtual-scroll-sticky-start="dense ? 24 : 48"
64-
@virtual-scroll="onVirtualScroll"
65-
:pagination.sync="pagination"
15+
row-key="name"
16+
selection="multiple"
17+
:selected.sync="selected"
18+
:hide-bottom="hideBottom"
19+
:hide-selected-banner="hideSelectedBanner"
20+
:hide-no-data="hideNoData"
21+
:hide-pagination="hidePagination"
22+
no-hover
6623
>
67-
<template v-slot:header="props">
68-
<q-tr :props="props">
69-
<q-th v-for="col in props.cols" :key="col.name" :props="props">
70-
{{ col.label }}
71-
</q-th>
72-
</q-tr>
73-
</template>
74-
7524
<template v-slot:body="props">
7625
<q-tr :props="props">
77-
<q-td v-for="col in props.cols" :key="col.name" :props="props">
78-
{{ col.value }}
26+
<q-td auto-width>
27+
<q-toggle dense v-model="props.selected" />
28+
</q-td>
29+
<q-td key="desc" :props="props" no-hover>
30+
{{ props.rowIndex }} / {{ props.pageIndex }} -
31+
{{ props.row.name }}
32+
<q-btn dense round flat :icon="props.expand ? 'arrow_drop_up' : 'arrow_drop_down'" @click="props.expand = !props.expand" />
33+
</q-td>
34+
<q-td key="calories" :props="props">{{ props.row.calories }}</q-td>
35+
<q-td key="fat" :props="props">{{ props.row.fat }}</q-td>
36+
<q-td key="carbs" :props="props">{{ props.row.carbs }}</q-td>
37+
<q-td key="protein" :props="props">{{ props.row.protein }}</q-td>
38+
<q-td key="sodium" :props="props">{{ props.row.sodium }}</q-td>
39+
<q-td key="calcium" :props="props">{{ props.row.calcium }}</q-td>
40+
<q-td key="iron" :props="props">
41+
<q-badge color="amber">
42+
{{ props.row.iron }}
43+
</q-badge>
7944
</q-td>
8045
</q-tr>
81-
</template>
82-
</q-table>
83-
<div class="q-pa-md">
84-
<q-input
85-
type="number"
86-
:value="listIndex"
87-
:min="0"
88-
:max="pagination.rowsPerPage === 0 ? listSize : pagination.rowsPerPage - 1"
89-
label="Scroll to index"
90-
input-class="text-right"
91-
@input="onIndexChange"
92-
/>
93-
</div>
94-
95-
<h2>With slots & different sizes</h2>
96-
<q-table
97-
:dense="dense"
98-
table-style="max-height: 500px"
99-
class="table-sticky"
100-
:separator="separator"
101-
:data="data"
102-
:columns="columns"
103-
:title="title"
104-
:filter="filter"
105-
:loading="loading"
106-
:visible-columns="visibleColumns"
107-
row-key="index"
108-
virtual-scroll
109-
:virtual-scroll-sticky-start="dense ? 24 : 48"
110-
:pagination.sync="pagination"
111-
>
112-
<template v-slot:header="props">
113-
<q-tr :props="props">
114-
<q-th v-for="col in props.cols" :key="col.name" :props="props">
115-
{{ col.label }}
116-
</q-th>
117-
</q-tr>
118-
</template>
119-
120-
<template v-slot:body="props">
121-
<q-tr :props="props">
122-
<q-td v-for="col in props.cols" :key="col.name" :props="props">
123-
{{ col.value }}
124-
<div v-if="pagination.page % 2 === 0" style="height: 50px;" />
46+
<q-tr v-show="props.expand" :props="props" no-hover>
47+
<q-td colspan="100%">
48+
<q-table
49+
:data="rows"
50+
:columns="columns"
51+
>
52+
<q-tr :props="props" />
53+
</q-table>
12554
</q-td>
12655
</q-tr>
12756
</template>
@@ -130,7 +59,7 @@
13059
</template>
13160

13261
<script>
133-
const seed = [
62+
const rows = [
13463
{
13564
name: 'Frozen Yogurt',
13665
calories: 159,
@@ -233,89 +162,42 @@ const seed = [
233162
}
234163
]
235164
236-
// we generate lots of rows here
237-
let data = []
238-
const listSize = 1000
239-
for (let i = 0; i < listSize; i++) {
240-
data = data.concat(seed.slice(0).map(r => ({ ...r })))
241-
}
242-
data.forEach((row, index) => {
243-
row.index = index
244-
})
245-
246165
export default {
247166
data () {
248167
return {
249-
dense: false,
250-
title: 'QDataTable',
251-
filter: '',
252-
loading: false,
253-
visibleColumns: ['index', 'desc', 'fat', 'carbs', 'protein', 'sodium', 'calcium', 'iron'],
254-
separator: 'horizontal',
255-
pagination: {
256-
rowsPerPage: 0
257-
},
258-
259-
listSize: listSize * seed.length - 1,
260-
listIndex: 50,
261-
168+
hideBottom: false,
169+
hideSelectedBanner: false,
170+
hideNoData: false,
171+
hidePagination: false,
172+
selected: [],
262173
columns: [
263-
{
264-
name: 'index',
265-
label: '#',
266-
field: 'index'
267-
},
268174
{
269175
name: 'desc',
270176
required: true,
271177
label: 'Dessert (100g serving)',
272178
align: 'left',
273179
field: row => row.name,
274-
format: val => `~${val}`,
180+
format: val => `${val}`,
275181
sortable: true
276182
},
277183
{ name: 'calories', align: 'center', label: 'Calories', field: 'calories', sortable: true },
278-
{ name: 'fat', label: 'Fat (g)', field: 'fat', sortable: true },
184+
{ name: 'fat', label: 'Fat (g)', field: 'fat', sortable: true, style: 'width: 10px' },
279185
{ name: 'carbs', label: 'Carbs (g)', field: 'carbs' },
280186
{ name: 'protein', label: 'Protein (g)', field: 'protein' },
281187
{ name: 'sodium', label: 'Sodium (mg)', field: 'sodium' },
282188
{ name: 'calcium', label: 'Calcium (%)', field: 'calcium', sortable: true, sort: (a, b) => parseInt(a, 10) - parseInt(b, 10) },
283189
{ name: 'iron', label: 'Iron (%)', field: 'iron', sortable: true, sort: (a, b) => parseInt(a, 10) - parseInt(b, 10) }
284-
]
190+
],
191+
rows
285192
}
286193
},
287194
288195
methods: {
289-
onIndexChange (index) {
290-
this.$refs.virtualScrollTable.scrollTo(index)
291-
},
292-
onVirtualScroll ({ index }) {
293-
this.listIndex = index
196+
toggleData () {
197+
this.rows = this.rows.length === 0
198+
? rows
199+
: []
294200
}
295-
},
296-
297-
created () {
298-
this.data = data
299-
},
300-
301-
mounted () {
302-
this.$refs.virtualScrollTable.scrollTo(this.listIndex)
303201
}
304202
}
305203
</script>
306-
307-
<style lang="stylus">
308-
.table-sticky
309-
.q-table__top,
310-
.q-table__bottom,
311-
thead tr:first-child th /* bg color is important for th; just specify one */
312-
background-color: #c1f4cd
313-
314-
thead tr th
315-
position: sticky
316-
z-index: 1
317-
thead tr:last-child th // this will be the loading indicator
318-
top: 48px // height of all previous header rows
319-
thead tr:first-child th
320-
top: 0
321-
</style>

0 commit comments

Comments
 (0)