4
4
v-slot =" { open }"
5
5
:by =" by"
6
6
:name =" name"
7
- :model-value =" modelValue"
7
+ :model-value =" multiple ? (Array.isArray(modelValue) ? modelValue : []) : modelValue"
8
8
:multiple =" multiple"
9
9
:disabled =" disabled"
10
10
as =" div"
30
30
<slot :open =" open" :disabled =" disabled" :loading =" loading" >
31
31
<button :id =" inputId" :class =" selectClass" :disabled =" disabled" type =" button" v-bind =" attrs" >
32
32
<span v-if =" (isLeading && leadingIconName) || $slots.leading" :class =" leadingWrapperIconClass" >
33
- <slot name =" leading" :disabled =" disabled" :loading =" loading" >
33
+ <slot name =" leading" :selected = " selected " : disabled =" disabled" :loading =" loading" >
34
34
<UIcon :name =" leadingIconName" :class =" leadingIconClass" />
35
35
</slot >
36
36
</span >
37
37
38
- <slot name =" label" >
38
+ <slot name =" label" :selected = " selected " >
39
39
<span v-if =" label" :class =" uiMenu.label" >{{ label }}</span >
40
40
<span v-else :class =" uiMenu.label" >{{ placeholder || '  ; ' }}</span >
41
41
</slot >
42
42
43
43
<span v-if =" (isTrailing && trailingIconName) || $slots.trailing" :class =" trailingWrapperIconClass" >
44
- <slot name =" trailing" :disabled =" disabled" :loading =" loading" >
44
+ <slot name =" trailing" :selected = " selected " : disabled =" disabled" :loading =" loading" >
45
45
<UIcon :name =" trailingIconName" :class =" trailingIconClass" aria-hidden =" true" />
46
46
</slot >
47
47
</span >
68
68
<component
69
69
:is =" searchable ? 'HComboboxOption' : 'HListboxOption'"
70
70
v-for =" (option, index) in filteredOptions"
71
- v-slot =" { active, selected, disabled: optionDisabled }"
71
+ v-slot =" { active, selected: optionSelected , disabled: optionDisabled }"
72
72
:key =" index"
73
73
as =" template"
74
74
:value =" valueAttribute ? option[valueAttribute] : option"
75
75
:disabled =" option.disabled"
76
76
>
77
- <li :class =" [uiMenu.option.base, uiMenu.option.rounded, uiMenu.option.padding, uiMenu.option.size, uiMenu.option.color, active ? uiMenu.option.active : uiMenu.option.inactive, selected && uiMenu.option.selected, optionDisabled && uiMenu.option.disabled]" >
77
+ <li :class =" [uiMenu.option.base, uiMenu.option.rounded, uiMenu.option.padding, uiMenu.option.size, uiMenu.option.color, active ? uiMenu.option.active : uiMenu.option.inactive, optionSelected && uiMenu.option.selected, optionDisabled && uiMenu.option.disabled]" >
78
78
<div :class =" uiMenu.option.container" >
79
- <slot name =" option" :option =" option" :active =" active" :selected =" selected " >
79
+ <slot name =" option" :option =" option" :active =" active" :selected =" optionSelected " >
80
80
<UIcon v-if =" option.icon" :name =" option.icon" :class =" [uiMenu.option.icon.base, active ? uiMenu.option.icon.active : uiMenu.option.icon.inactive, option.iconClass]" aria-hidden =" true" />
81
81
<UAvatar
82
82
v-else-if =" option.avatar"
90
90
</slot >
91
91
</div >
92
92
93
- <span v-if =" selected " :class =" [uiMenu.option.selectedIcon.wrapper, uiMenu.option.selectedIcon.padding]" >
93
+ <span v-if =" optionSelected " :class =" [uiMenu.option.selectedIcon.wrapper, uiMenu.option.selectedIcon.padding]" >
94
94
<UIcon :name =" selectedIcon" :class =" uiMenu.option.selectedIcon.base" aria-hidden =" true" />
95
95
</span >
96
96
</li >
97
97
</component >
98
98
99
- <component :is =" searchable ? 'HComboboxOption' : 'HListboxOption'" v-if =" creatable && createOption" v-slot =" { active, selected }" :value =" createOption" as =" template" >
99
+ <component :is =" searchable ? 'HComboboxOption' : 'HListboxOption'" v-if =" creatable && createOption" v-slot =" { active, selected: optionSelected }" :value =" createOption" as =" template" >
100
100
<li :class =" [uiMenu.option.base, uiMenu.option.rounded, uiMenu.option.padding, uiMenu.option.size, uiMenu.option.color, active ? uiMenu.option.active : uiMenu.option.inactive]" >
101
101
<div :class =" uiMenu.option.container" >
102
- <slot name =" option-create" :option =" createOption" :active =" active" :selected =" selected " >
102
+ <slot name =" option-create" :option =" createOption" :active =" active" :selected =" optionSelected " >
103
103
<span :class =" uiMenu.option.create" >Create "{{ createOption[optionAttribute] }}"</span >
104
104
</slot >
105
105
</div >
@@ -335,6 +335,10 @@ export default defineComponent({
335
335
},
336
336
emits: [' update:modelValue' , ' update:query' , ' open' , ' close' , ' change' ],
337
337
setup (props , { emit , slots }) {
338
+ if (import .meta .dev && props .multiple && ! Array .isArray (props .modelValue )) {
339
+ console .warn (` [@nuxt/ui] The USelectMenu components needs to have a modelValue of type Array when using the multiple prop. Got '${typeof props .modelValue }' instead. ` , props .modelValue )
340
+ }
341
+
338
342
const { ui, attrs } = useUI (' select' , toRef (props , ' ui' ), config , toRef (props , ' class' ))
339
343
const { ui : uiMenu } = useUI (' selectMenu' , toRef (props , ' uiMenu' ), configMenu )
340
344
@@ -358,17 +362,34 @@ export default defineComponent({
358
362
}
359
363
})
360
364
365
+ const selected = computed (() => {
366
+ if (props .multiple ) {
367
+ if (! Array .isArray (props .modelValue ) || ! props .modelValue .length ) {
368
+ return []
369
+ }
370
+
371
+ if (props .valueAttribute ) {
372
+ return options .value .filter (option => (props .modelValue as any []).includes (option [props .valueAttribute ]))
373
+ }
374
+ return options .value .filter (option => (props .modelValue as any []).includes (option ))
375
+ }
376
+
377
+ if (props .valueAttribute ) {
378
+ return options .value .find (option => option [props .valueAttribute ] === props .modelValue )
379
+ }
380
+ return options .value .find (option => option === props .modelValue )
381
+ })
382
+
361
383
const label = computed (() => {
362
384
if (props .multiple ) {
363
385
if (Array .isArray (props .modelValue ) && props .modelValue .length ) {
364
- return ` ${props . modelValue .length } selected `
386
+ return ` ${selected . value .length } selected `
365
387
} else {
366
388
return null
367
389
}
368
390
} else if (props .modelValue !== undefined && props .modelValue !== null ) {
369
391
if (props .valueAttribute ) {
370
- const option = options .value .find (option => option [props .valueAttribute ] === props .modelValue )
371
- return option ? option [props .optionAttribute ] : null
392
+ return selected .value ?.[props .optionAttribute ] ?? null
372
393
} else {
373
394
return [' string' , ' number' ].includes (typeof props .modelValue ) ? props .modelValue : props .modelValue [props .optionAttribute ]
374
395
}
@@ -543,6 +564,7 @@ export default defineComponent({
543
564
popper ,
544
565
trigger ,
545
566
container ,
567
+ selected ,
546
568
label ,
547
569
isLeading ,
548
570
isTrailing ,
0 commit comments