feat : ajout d'un sélecteur "Tout cocher" dans le composant SelectCheckbox
This commit is contained in:
@@ -100,6 +100,29 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="rounded-lg border p-4">
|
||||||
|
<h2 class="mb-4 text-xl font-bold">Tout sélectionner</h2>
|
||||||
|
<MalioSelectCheckbox
|
||||||
|
v-model="selectAllValue"
|
||||||
|
:options="options"
|
||||||
|
label="Pays"
|
||||||
|
:display-select-all="true"
|
||||||
|
empty-option-label="Aucune selection"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="rounded-lg border p-4">
|
||||||
|
<h2 class="mb-4 text-xl font-bold">Tout sélectionner (label custom)</h2>
|
||||||
|
<MalioSelectCheckbox
|
||||||
|
v-model="selectAllCustomValue"
|
||||||
|
:options="options"
|
||||||
|
label="Pays"
|
||||||
|
:display-select-all="true"
|
||||||
|
select-all-label="Cocher tout"
|
||||||
|
empty-option-label="Aucune selection"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="rounded-lg border p-4 md:col-span-2">
|
<div class="rounded-lg border p-4 md:col-span-2">
|
||||||
<h2 class="mb-4 text-xl font-bold">Liste longue</h2>
|
<h2 class="mb-4 text-xl font-bold">Liste longue</h2>
|
||||||
<MalioSelectCheckbox
|
<MalioSelectCheckbox
|
||||||
@@ -163,6 +186,8 @@ const errorValue = ref<Array<string | number>>([])
|
|||||||
const successValue = ref<Array<string | number>>(['be'])
|
const successValue = ref<Array<string | number>>(['be'])
|
||||||
const disabledValue = ref<Array<string | number>>(['ca'])
|
const disabledValue = ref<Array<string | number>>(['ca'])
|
||||||
const emptyValue = ref<Array<string | number>>([])
|
const emptyValue = ref<Array<string | number>>([])
|
||||||
|
const selectAllValue = ref<Array<string | number>>([])
|
||||||
|
const selectAllCustomValue = ref<Array<string | number>>([])
|
||||||
const longListValue = ref<Array<string | number>>([])
|
const longListValue = ref<Array<string | number>>([])
|
||||||
const bottomValue = ref<Array<string | number>>([])
|
const bottomValue = ref<Array<string | number>>([])
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ type SelectCheckboxProps = {
|
|||||||
textLabel?: string
|
textLabel?: string
|
||||||
rounded?: string
|
rounded?: string
|
||||||
displayTag?: boolean
|
displayTag?: boolean
|
||||||
|
displaySelectAll?: boolean
|
||||||
|
selectAllLabel?: string
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,4 +94,85 @@ describe('MalioSelectCheckbox', () => {
|
|||||||
expect(wrapper.text()).not.toContain('0/3')
|
expect(wrapper.text()).not.toContain('0/3')
|
||||||
expect(wrapper.text()).toContain('Aucune selection')
|
expect(wrapper.text()).toContain('Aucune selection')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('does not show select all checkbox by default', async () => {
|
||||||
|
const wrapper = mount(SelectCheckboxForTest, {
|
||||||
|
props: {modelValue: [], options},
|
||||||
|
})
|
||||||
|
|
||||||
|
await wrapper.get('button').trigger('click')
|
||||||
|
|
||||||
|
const checkboxes = wrapper.findAll('input[type="checkbox"]')
|
||||||
|
expect(checkboxes).toHaveLength(options.length)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('shows select all checkbox when displaySelectAll is true', async () => {
|
||||||
|
const wrapper = mount(SelectCheckboxForTest, {
|
||||||
|
props: {modelValue: [], options, displaySelectAll: true},
|
||||||
|
})
|
||||||
|
|
||||||
|
await wrapper.get('button').trigger('click')
|
||||||
|
|
||||||
|
const checkboxes = wrapper.findAll('input[type="checkbox"]')
|
||||||
|
expect(checkboxes).toHaveLength(options.length + 1)
|
||||||
|
expect(wrapper.text()).toContain('Tout sélectionner')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('shows custom select all label', async () => {
|
||||||
|
const wrapper = mount(SelectCheckboxForTest, {
|
||||||
|
props: {modelValue: [], options, displaySelectAll: true, selectAllLabel: 'Sélectionner tout'},
|
||||||
|
})
|
||||||
|
|
||||||
|
await wrapper.get('button').trigger('click')
|
||||||
|
|
||||||
|
expect(wrapper.text()).toContain('Sélectionner tout')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('emits all values when select all is clicked and none selected', async () => {
|
||||||
|
const wrapper = mount(SelectCheckboxForTest, {
|
||||||
|
props: {modelValue: [], options, displaySelectAll: true},
|
||||||
|
})
|
||||||
|
|
||||||
|
await wrapper.get('button').trigger('click')
|
||||||
|
|
||||||
|
const checkboxes = wrapper.findAll('input[type="checkbox"]')
|
||||||
|
await checkboxes[0].setValue(true)
|
||||||
|
|
||||||
|
expect(wrapper.emitted('update:modelValue')?.[0]).toEqual([['fr', 'be', 'ca']])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('emits empty array when select all is clicked and all selected', async () => {
|
||||||
|
const wrapper = mount(SelectCheckboxForTest, {
|
||||||
|
props: {modelValue: ['fr', 'be', 'ca'], options, displaySelectAll: true},
|
||||||
|
})
|
||||||
|
|
||||||
|
await wrapper.get('button').trigger('click')
|
||||||
|
|
||||||
|
const checkboxes = wrapper.findAll('input[type="checkbox"]')
|
||||||
|
await checkboxes[0].setValue(false)
|
||||||
|
|
||||||
|
expect(wrapper.emitted('update:modelValue')?.[0]).toEqual([[]])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('select all checkbox is checked when all options are selected', async () => {
|
||||||
|
const wrapper = mount(SelectCheckboxForTest, {
|
||||||
|
props: {modelValue: ['fr', 'be', 'ca'], options, displaySelectAll: true},
|
||||||
|
})
|
||||||
|
|
||||||
|
await wrapper.get('button').trigger('click')
|
||||||
|
|
||||||
|
const checkboxes = wrapper.findAll('input[type="checkbox"]')
|
||||||
|
expect((checkboxes[0].element as HTMLInputElement).checked).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('select all checkbox is unchecked when not all options are selected', async () => {
|
||||||
|
const wrapper = mount(SelectCheckboxForTest, {
|
||||||
|
props: {modelValue: ['fr'], options, displaySelectAll: true},
|
||||||
|
})
|
||||||
|
|
||||||
|
await wrapper.get('button').trigger('click')
|
||||||
|
|
||||||
|
const checkboxes = wrapper.findAll('input[type="checkbox"]')
|
||||||
|
expect((checkboxes[0].element as HTMLInputElement).checked).toBe(false)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -143,6 +143,21 @@
|
|||||||
: 'border-m-primary'
|
: 'border-m-primary'
|
||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
|
<li
|
||||||
|
v-if="displaySelectAll"
|
||||||
|
class="border-b border-m-muted/30 px-3 py-2"
|
||||||
|
@mousedown.prevent
|
||||||
|
>
|
||||||
|
<Checkbox
|
||||||
|
:model-value="allSelected"
|
||||||
|
:label="selectAllLabel"
|
||||||
|
:disabled="disabled"
|
||||||
|
group-class="!mt-0"
|
||||||
|
label-class="option-checkbox w-full cursor-pointer font-semibold"
|
||||||
|
tabindex="-1"
|
||||||
|
@update:model-value="toggleAll"
|
||||||
|
/>
|
||||||
|
</li>
|
||||||
<li
|
<li
|
||||||
v-for="(opt, index) in normalizedOptions"
|
v-for="(opt, index) in normalizedOptions"
|
||||||
:id="optionId(index)"
|
:id="optionId(index)"
|
||||||
@@ -212,6 +227,8 @@ const props = withDefaults(defineProps<{
|
|||||||
textLabel?: string
|
textLabel?: string
|
||||||
rounded?: string
|
rounded?: string
|
||||||
displayTag?: boolean
|
displayTag?: boolean
|
||||||
|
displaySelectAll?: boolean
|
||||||
|
selectAllLabel?: string
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
}>(), {
|
}>(), {
|
||||||
options: () => [],
|
options: () => [],
|
||||||
@@ -227,6 +244,8 @@ const props = withDefaults(defineProps<{
|
|||||||
textLabel: 'text-sm',
|
textLabel: 'text-sm',
|
||||||
rounded: 'rounded-md',
|
rounded: 'rounded-md',
|
||||||
displayTag: false,
|
displayTag: false,
|
||||||
|
displaySelectAll: false,
|
||||||
|
selectAllLabel: 'Tout sélectionner',
|
||||||
disabled: false,
|
disabled: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -330,6 +349,19 @@ function toggle() {
|
|||||||
open()
|
open()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const allSelected = computed(() =>
|
||||||
|
normalizedOptions.value.length > 0
|
||||||
|
&& normalizedOptions.value.every(opt => props.modelValue.includes(opt.value)),
|
||||||
|
)
|
||||||
|
|
||||||
|
function toggleAll() {
|
||||||
|
if (allSelected.value) {
|
||||||
|
emit('update:modelValue', [])
|
||||||
|
} else {
|
||||||
|
emit('update:modelValue', normalizedOptions.value.map(opt => opt.value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function isChecked(value: string | number) {
|
function isChecked(value: string | number) {
|
||||||
return props.modelValue.includes(value)
|
return props.modelValue.includes(value)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user