11<script lang="ts" setup>
2- import { computed } from ' vue'
2+ import { computed , ref } from ' vue'
33
44import { getRandomId } from ' @/utils/random-utils'
55import DsfrPagination , { type Page } from ' ../DsfrPagination/DsfrPagination.vue'
@@ -11,6 +11,7 @@ const props = withDefaults(defineProps<DsfrDataTableProps>(), {
1111 bottomActionsRow : () => [],
1212 currentPage: 0 ,
1313 rowsPerPage: 10 ,
14+ rowKey: 0 ,
1415 paginationOptions : () => [
1516 5 ,
1617 10 ,
@@ -22,7 +23,7 @@ const emit = defineEmits<{
2223 ' update:current-page' : [page : number ]
2324}>()
2425
25- const selection = defineModel <string []>(' selection' )
26+ const selection = defineModel <string []>(' selection' , { default: [] } )
2627const rowsPerPage = defineModel <number >(' rowsPerPage' , { default: 10 })
2728const currentPage = defineModel <number >(' currentPage' , { default: 1 })
2829const pageCount = computed (() => Math .ceil (props .rows .length / rowsPerPage .value ))
@@ -52,6 +53,24 @@ const finalRows = computed(() => {
5253
5354 return rows
5455})
56+
57+ function selectAll (bool : boolean ) {
58+ if (bool ) {
59+ const keyIndex = props .headersRow .findIndex (header => (header as DsfrDataTableHeaderCellObject ).key ?? header )
60+ selection .value = finalRows .value .map (row => row [keyIndex ] as string )
61+ }
62+ selection .value ! .length = 0
63+ }
64+ const wholeSelection = ref (false )
65+ function checkSelection () {
66+ wholeSelection .value = selection .value .length === finalRows .value .length
67+ }
68+
69+ function onPaginationOptionsChange () {
70+ emit (' update:current-page' , 0 )
71+ wholeSelection .value = false
72+ selection .value .length = 0
73+ }
5574 </script >
5675
5776<template >
@@ -72,7 +91,21 @@ const finalRows = computed(() => {
7291 class =" fr-cell--fixed"
7392 role =" columnheader"
7493 >
75- <span class =" fr-sr-only" >Sélectionner</span >
94+ <div class =" fr-checkbox-group fr-checkbox-group--sm" >
95+ <!-- @vue-expect-error TS2538 -->
96+ <input
97+ :id =" `table-select--${id}-all`"
98+ :checked =" wholeSelection"
99+ type =" checkbox"
100+ @input =" selectAll($event.target.checked)"
101+ >
102+ <label
103+ class =" fr-label"
104+ :for =" `table-select--${id}-all`"
105+ >
106+ Sélectionner tout
107+ </label >
108+ </div >
76109 </th >
77110 <th
78111 v-for =" header of headersRow"
@@ -103,14 +136,15 @@ const finalRows = computed(() => {
103136 <div class =" fr-checkbox-group fr-checkbox-group--sm" >
104137 <!-- @vue-expect-error TS2538 -->
105138 <input
106- id =" table -select-checkbox-7748--0 "
139+ : id =" `row -select-${id}-${idx}` "
107140 v-model =" selection"
108- :value =" row [rowKey] ?? `row-${idx}`"
141+ :value =" rows[idx] [rowKey] ?? `row-${idx}`"
109142 type =" checkbox"
143+ @change =" checkSelection()"
110144 >
111145 <label
112146 class =" fr-label"
113- for =" table -select-checkbox-7748--0 "
147+ : for =" `row -select-${id}-${idx}` "
114148 >
115149 Sélectionner la ligne {{ idx + 1 }}
116150 </label >
@@ -141,51 +175,76 @@ const finalRows = computed(() => {
141175 </div >
142176 </div >
143177 </div >
144- <slot name =" pagination" >
145- <template
146- v-if =" pagination "
147- >
148- <div class =" flex" >
149- <div class =" fr-select-group flex" >
150- <label class =" fr-label" >Résultats par page : </label >
151- <select
152- v-model =" rowsPerPage"
153- class =" fr-select"
154- @change =" emit('update:current-page', 0)"
155- >
156- <option
157- value =" "
158- :selected =" !paginationOptions.includes(rowsPerPage)"
159- disabled =" true"
160- hidden =" hidden"
178+ <div
179+ :class =" bottomActionBarClass"
180+ >
181+ <slot name =" pagination" >
182+ <template
183+ v-if =" pagination && ! $slots .pagination "
184+ >
185+ <div
186+ class =" flex justify-between items-center"
187+ :class =" paginationWrapperClass"
188+ >
189+ <div class =" flex gap-2 items-center" >
190+ <label
191+ class =" fr-label"
192+ for =" pagination-options"
161193 >
162- Sélectionner une option
163- </option >
164- <option
165- v-for = " (option, idx) in paginationOptions "
166- :key = " idx "
167- :value = " option "
168- :selected = " +option === rowsPerPage "
194+ Résultats par page :
195+ </label >
196+ <select
197+ id = " pagination-options "
198+ v-model = " rowsPerPage "
199+ class = " fr-select "
200+ @change = " onPaginationOptionsChange() "
169201 >
170- {{ option }}
171- </option >
172- </select >
173- </div >
174- <div class =" flex ml-1" >
175- <span class =" self-center" >Page {{ currentPage + 1 }} sur {{ pageCount }}</span >
202+ <option
203+ value =" "
204+ :selected =" !paginationOptions.includes(rowsPerPage)"
205+ disabled =" true"
206+ hidden =" hidden"
207+ >
208+ Sélectionner une option
209+ </option >
210+ <option
211+ v-for =" (option, idx) in paginationOptions"
212+ :key =" idx"
213+ :value =" option"
214+ :selected =" +option === rowsPerPage"
215+ >
216+ {{ option }}
217+ </option >
218+ </select >
219+ </div >
220+ <div class =" flex ml-1" >
221+ <span class =" self-center" >Page {{ currentPage + 1 }} sur {{ pageCount }}</span >
222+ </div >
223+ <DsfrPagination
224+ v-model:current-page =" currentPage"
225+ :pages =" pages"
226+ />
176227 </div >
177- <DsfrPagination
178- v-model:current-page =" currentPage"
179- :pages =" pages"
180- />
181- </div >
182- </template >
183- </slot >
228+ </template >
229+ </slot >
230+ </div >
184231 </div >
185232</template >
186233
187234<style scoped>
188235.flex {
189236 display : flex ;
190237}
238+ .justify-between {
239+ justify-content : space-between ;
240+ }
241+ .items-center {
242+ align-items : center ;
243+ }
244+ .gap-2 {
245+ gap : 0.5rem ;
246+ }
247+ :deep(.fr-pagination__link ) {
248+ margin-bottom : 0 !important ;
249+ }
191250 </style >
0 commit comments