🌟 Introduction
Ce composant permet de gérer un ensemble de cases à cocher DSFR. Il est composé d'un libellé (legend
), d'options individuelles représentées par le composant DsfrCheckbox
, et d'un message d'information, d'erreur ou de validation global.
📐 Structure
Le composant DsfrCheckboxSet
est composé des éléments suivants :
- Un élément
<fieldset>
contenant l'ensemble des cases à cocher - Une légende (
legend
) définie par la proplegend
et personnalisable avec le slotlegend
- Un groupe de cases à cocher individuelles rendues par le composant
DsfrCheckbox
- Un message d'information, d'erreur ou de validation, affiché en dessous du groupe de cases à cocher
🛠️ Props
Nom | Type | Description | Obligatoire |
---|---|---|---|
options | (DsfrCheckboxProps & InputHTMLAttributes)[] | Tableau d'options définissant les cases à cocher individuelles | ✅ |
modelValue | string[] | Valeur courante du composant, un tableau de noms des cases cochées | ✅ |
disabled | boolean | Indique si l'ensemble des cases à cocher est désactivé | |
errorMessage | string | Message d'erreur global à afficher | |
inline | boolean | Affiche les cases à cocher en ligne (par défaut : false ) | |
legend | string | Texte de la légende | |
required | boolean | Indique si l'ensemble des cases à cocher est obligatoire | |
small | boolean | Affiche les cases à cocher en taille réduite | |
titleId | string | Identifiant unique du champ (générée automatiquement si non fournie) | |
validMessage | string | Message de validation global à afficher |
📡 Événements
DsfrCheckboxSet
émet l'événement suivant :
Nom | Description |
---|---|
update:modelValue | Est émis lorsque la sélection des cases à cocher change |
🧩 Slots
DsfrCheckboxSet
fournit les slots suivants pour la personnalisation :
legend
: Permet de personnaliser le contenu de la légende.required-tip
: Permet d'ajouter plus qu’un astérisque pour indiquer que le champ est obligatoire ou d’autres détails sur cette case à cocher.
🪆 Relation avec DsfrCheckbox
DsfrChecboxSet
utilise en interne DsfrCheckbox
, et permet de récupérer dans modelValue
sous forme de tableau non pas les états de chaque case à cocher, mais un tableau de string
contenant les valeurs de la prop name
de chaque case à cocher qui est cochée.
Cf. les exemples ci-dessous
📝 Exemples
vue
<script lang="ts" setup>
import { ref } from 'vue'
import DsfrCheckboxSet from '../DsfrCheckboxSet.vue'
const modelValue1 = ref(undefined)
const modelValue2 = ref(undefined)
const modelValue3 = ref(undefined)
const modelValue4 = ref(undefined)
const modelValue5 = ref(undefined)
const modelValue6 = ref(undefined)
const options1 = [
{
label: 'Première valeur',
id: 'name1-1',
name: 'name1-1',
hint: 'Description de la première valeur',
},
{
label: 'Deuxième valeur',
id: 'name1-2',
name: 'name1-2',
hint: 'Description de la deuxième valeur',
},
{
label: 'Troisième valeur',
id: 'name1-3',
name: 'name1-3',
hint: 'Description de la troisième valeur',
},
] as const
const options2 = structuredClone(options1).map(option => Object.fromEntries(
Object.entries(option).map(([key, value]) => [key, value.replace('name1', 'name2')]),
))
const options3 = structuredClone(options1).map(option => Object.fromEntries(
Object.entries(option).map(([key, value]) => [key, value.replace('name1', 'name3')]),
))
const options4 = structuredClone(options1).map(option => Object.fromEntries(
Object.entries(option).filter(([key]) => key !== 'hint').map(([key, value]) => [key, value.replace('name1', 'name4')]),
))
const options5 = structuredClone(options1).map(option => Object.fromEntries(
Object.entries(option).filter(([key]) => key !== 'hint').map(([key, value]) => [key, value.replace('name1', 'name5')]),
))
const options6 = structuredClone(options1).map(option => Object.fromEntries(
Object.entries(option).filter(([key]) => key !== 'hint').map(([key, value]) => [key, value.replace('name1', 'name6')]),
))
const errorMessage = 'Message d’erreur'
const validMessage = 'Message de validation'
</script>
<template>
<div class="fr-container fr-my-2v">
<div class="fr-my-2v">
<DsfrCheckboxSet
v-model="modelValue1"
legend="Groupe de cases à cocher simple"
:options="options1"
/>
<p>
modelValue1: {{ modelValue1 }}
</p>
</div>
<div class="fr-my-2v">
<DsfrCheckboxSet
v-model="modelValue2"
legend="Groupe de cases à cocher avec erreur"
:options="options2"
:error-message="errorMessage"
/>
<p>
modelValue2: {{ modelValue2 }}
</p>
</div>
<div class="fr-my-2v">
<DsfrCheckboxSet
v-model="modelValue3"
legend="Groupe de cases à cocher avec message de validation"
:options="options3"
:valid-message="validMessage"
/>
<p>
modelValue3: {{ modelValue3 }}
</p>
</div>
<div class="fr-my-2v">
<DsfrCheckboxSet
v-model="modelValue4"
legend="Groupe de cases à cocher en ligne"
:options="options4"
inline
/>
<p>
modelValue4: {{ modelValue4 }}
</p>
</div>
<div class="fr-my-2v">
<DsfrCheckboxSet
v-model="modelValue5"
legend="Groupe de cases à cocher en ligne avec erreur"
:options="options5"
inline
error-message="Message d’erreur"
/>
<p>
modelValue5: {{ modelValue5 }}
</p>
</div>
<div class="fr-my-2v">
<DsfrCheckboxSet
v-model="modelValue6"
legend="Groupe de cases à cocher en ligne avec erreur"
:options="options6"
inline
valid-message="Message de validation"
/>
<p>
modelValue6: {{ modelValue6 }}
</p>
</div>
</div>
</template>
⚙️ Code source du composant
vue
<script lang="ts" setup>
import { computed } from 'vue'
import DsfrCheckbox from './DsfrCheckbox.vue'
import { getRandomId } from '../../utils/random-utils'
import type { DsfrCheckboxSetProps } from './DsfrCheckbox.types'
export type { DsfrCheckboxSetProps }
const props = withDefaults(defineProps<DsfrCheckboxSetProps>(), {
titleId: () => getRandomId('checkbox', 'group'),
errorMessage: '',
validMessage: '',
legend: '',
options: () => [],
modelValue: () => [],
})
const emit = defineEmits<{ (e: 'update:modelValue', payload: string[]): void }>()
const message = computed(() => {
return props.errorMessage || props.validMessage
})
const additionalMessageClass = computed(() => {
return props.errorMessage ? 'fr-error-text' : 'fr-valid-text'
})
const onChange = ({ name, checked }: { name: string, checked: boolean }) => {
const selected = checked
? [...props.modelValue, name]
: props.modelValue.filter(val => val !== name)
emit('update:modelValue', selected)
}
</script>
<template>
<div class="fr-form-group">
<fieldset
class="fr-fieldset"
:class="{
'fr-fieldset--error': errorMessage,
'fr-fieldset--valid': !errorMessage && validMessage,
}"
:disabled="disabled"
:aria-labelledby="`${titleId} messages-${titleId}`"
:role="(errorMessage || validMessage) ? 'group' : undefined"
>
<legend
:id="titleId"
class="fr-fieldset__legend fr-text--regular"
>
<!-- @slot Slot pour personnaliser tout le contenu de la balise <legend> cf. [DsfrInput](/?path=/story/composants-champ-de-saisie-champ-simple-dsfrinput--champ-avec-label-personnalise). Une **rte le même nom pour une légende simple** (texte sans mise en forme) -->
<slot name="legend">
{{ legend }}
<!-- @slot Slot pour indiquer que le champ est obligatoire. Par défaut, met une astérisque si `required` est à true (dans un `<span class="required">`) -->
<slot name="required-tip">
<span
v-if="required"
class="required"
> *</span>
</slot>
</slot>
</legend>
<slot>
<DsfrCheckbox
v-for="option in options"
:id="option.id"
:key="option.id || option.name"
:name="option.name"
:label="option.label"
:disabled="option.disabled"
:aria-disabled="option.disabled"
:small="small"
:inline="inline"
:model-value="modelValue.includes(option.name)"
:hint="option.hint"
@update:model-value="onChange({ name: option.name, checked: $event })"
/>
</slot>
<div
v-if="message"
:id="`messages-${titleId}`"
class="fr-messages-group"
>
<p
class="fr-message--info flex items-center"
:class="additionalMessageClass"
>
<span>{{ message }}</span>
</p>
</div>
</fieldset>
</div>
</template>
ts
import type { InputHTMLAttributes } from 'vue'
export type DsfrCheckboxProps = {
id?: string
name: string
required?: boolean
modelValue?: boolean
small?: boolean
inline?: boolean
label?: string
errorMessage?: string
validMessage?: string
hint?: string
}
export type DsfrCheckboxSetProps = {
titleId?: string
disabled?: boolean
inline?: boolean
required?: boolean
small?: boolean
errorMessage?: string
validMessage?: string
legend?: string
options?: (DsfrCheckboxProps & InputHTMLAttributes)[]
modelValue?: string[]
}