Skip to content

Commit

Permalink
feat(DsfrDataTable): ✨ permet de sélectionner toutes lignes
Browse files Browse the repository at this point in the history
  • Loading branch information
laruiss committed Sep 4, 2024
1 parent 89ff17f commit cc663da
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 45 deletions.
2 changes: 2 additions & 0 deletions src/components/DsfrDataTable/DsfrDataTable.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@ export type DsfrDataTableProps = {
paginationOptions?: number[]
currentPage?: number
rowsPerPage?: number
bottomActionBarClass?: string | Record<string, boolean> | Array<string | Record<string, boolean>>
paginationWrapperClass?: string | Record<string, boolean> | Array<string | Record<string, boolean>>
}
145 changes: 102 additions & 43 deletions src/components/DsfrDataTable/DsfrDataTable.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script lang="ts" setup>
import { computed } from 'vue'
import { computed, ref } from 'vue'
import { getRandomId } from '@/utils/random-utils'
import DsfrPagination, { type Page } from '../DsfrPagination/DsfrPagination.vue'
Expand All @@ -11,6 +11,7 @@ const props = withDefaults(defineProps<DsfrDataTableProps>(), {
bottomActionsRow: () => [],
currentPage: 0,
rowsPerPage: 10,
rowKey: 0,
paginationOptions: () => [
5,
10,
Expand All @@ -22,7 +23,7 @@ const emit = defineEmits<{
'update:current-page': [page: number]
}>()
const selection = defineModel<string[]>('selection')
const selection = defineModel<string[]>('selection', { default: [] })
const rowsPerPage = defineModel<number>('rowsPerPage', { default: 10 })
const currentPage = defineModel<number>('currentPage', { default: 1 })
const pageCount = computed(() => Math.ceil(props.rows.length / rowsPerPage.value))
Expand Down Expand Up @@ -52,6 +53,24 @@ const finalRows = computed(() => {
return rows
})
function selectAll (bool: boolean) {
if (bool) {
const keyIndex = props.headersRow.findIndex(header => (header as DsfrDataTableHeaderCellObject).key ?? header)
selection.value = finalRows.value.map(row => row[keyIndex] as string)
}
selection.value!.length = 0
}
const wholeSelection = ref(false)
function checkSelection () {
wholeSelection.value = selection.value.length === finalRows.value.length
}
function onPaginationOptionsChange () {
emit('update:current-page', 0)
wholeSelection.value = false
selection.value.length = 0
}
</script>

<template>
Expand All @@ -72,7 +91,21 @@ const finalRows = computed(() => {
class="fr-cell--fixed"
role="columnheader"
>
<span class="fr-sr-only">Sélectionner</span>
<div class="fr-checkbox-group fr-checkbox-group--sm">
<!-- @vue-expect-error TS2538 -->
<input
:id="`table-select--${id}-all`"
:checked="wholeSelection"
type="checkbox"
@input="selectAll($event.target.checked)"
>
<label
class="fr-label"
:for="`table-select--${id}-all`"
>
Sélectionner tout
</label>
</div>
</th>
<th
v-for="header of headersRow"
Expand Down Expand Up @@ -103,14 +136,15 @@ const finalRows = computed(() => {
<div class="fr-checkbox-group fr-checkbox-group--sm">
<!-- @vue-expect-error TS2538 -->
<input
id="table-select-checkbox-7748--0"
:id="`row-select-${id}-${idx}`"
v-model="selection"
:value="row[rowKey] ?? `row-${idx}`"
:value="rows[idx][rowKey] ?? `row-${idx}`"
type="checkbox"
@change="checkSelection()"
>
<label
class="fr-label"
for="table-select-checkbox-7748--0"
:for="`row-select-${id}-${idx}`"
>
Sélectionner la ligne {{ idx + 1 }}
</label>
Expand Down Expand Up @@ -141,51 +175,76 @@ const finalRows = computed(() => {
</div>
</div>
</div>
<slot name="pagination">
<template
v-if="pagination"
>
<div class="flex">
<div class="fr-select-group flex">
<label class="fr-label">Résultats par page : </label>
<select
v-model="rowsPerPage"
class="fr-select"
@change="emit('update:current-page', 0)"
>
<option
value=""
:selected="!paginationOptions.includes(rowsPerPage)"
disabled="true"
hidden="hidden"
<div
:class="bottomActionBarClass"
>
<slot name="pagination">
<template
v-if="pagination && !$slots.pagination"
>
<div
class="flex justify-between items-center"
:class="paginationWrapperClass"
>
<div class="flex gap-2 items-center">
<label
class="fr-label"
for="pagination-options"
>
Sélectionner une option
</option>
<option
v-for="(option, idx) in paginationOptions"
:key="idx"
:value="option"
:selected="+option === rowsPerPage"
Résultats par page :
</label>
<select
id="pagination-options"
v-model="rowsPerPage"
class="fr-select"
@change="onPaginationOptionsChange()"
>
{{ option }}
</option>
</select>
</div>
<div class="flex ml-1">
<span class="self-center">Page {{ currentPage + 1 }} sur {{ pageCount }}</span>
<option
value=""
:selected="!paginationOptions.includes(rowsPerPage)"
disabled="true"
hidden="hidden"
>
Sélectionner une option
</option>
<option
v-for="(option, idx) in paginationOptions"
:key="idx"
:value="option"
:selected="+option === rowsPerPage"
>
{{ option }}
</option>
</select>
</div>
<div class="flex ml-1">
<span class="self-center">Page {{ currentPage + 1 }} sur {{ pageCount }}</span>
</div>
<DsfrPagination
v-model:current-page="currentPage"
:pages="pages"
/>
</div>
<DsfrPagination
v-model:current-page="currentPage"
:pages="pages"
/>
</div>
</template>
</slot>
</template>
</slot>
</div>
</div>
</template>
<style scoped>
.flex {
display: flex;
}
.justify-between {
justify-content: space-between;
}
.items-center {
align-items: center;
}
.gap-2 {
gap: 0.5rem;
}
:deep(.fr-pagination__link) {
margin-bottom: 0 !important;
}
</style>
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,20 @@ const currentPage = ref<number>(0)
</script>

<template>
<div class="fr-container fr-my-2v">
<div class="fr-container fr-my-2v w-[800px]">
<DsfrDataTable
v-model:selection="selection"
v-model:current-page="currentPage"
:headers-row="headers"
:rows="rows"
selectable-rows
:row-key="0"
row-key="id"
title="Titre du tableau (caption)"
pagination
:rows-per-page="2"
:pagination-options="[1, 2, 3]"
bottom-action-bar-class="bottom-action-bar-class"
pagination-wrapper-class="pagination-wrapper-class"
>
<template #header="{ key, label }">
<div @click="click($event, key)">
Expand All @@ -65,3 +67,12 @@ const currentPage = ref<number>(0)
IDs sélectionnées : {{ selection }}
</div>
</template>

<style scoped>
:deep(.bottom-action-bar-class) {
width: 860px;
}
:deep(.pagination-wrapper-class) {
width: 860px;
}
</style>

0 comments on commit cc663da

Please sign in to comment.