Skip to content

Commit 03b2a72

Browse files
committed
feat: add limit attr to input-select
1 parent 900ac31 commit 03b2a72

File tree

5 files changed

+43
-4
lines changed

5 files changed

+43
-4
lines changed

docs/inputs/input-select.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,13 @@ If no value is selected, a text label is shown.
5757

5858
Данный параметр позволяет использовать множественную выборку. В таком случае modelValue будет обрабатываться как массив.
5959

60+
### limit <Badge type = "info">Optional</Badge>
61+
62+
- Type `number`
63+
64+
Данный параметр устанавливает предельное количество выбираемых элементов, если используется атрибут `multiple`.
65+
66+
6067
____
6168

6269
Also, all parameters common to all `FormField`. Information about them can be viewed
@@ -147,6 +154,12 @@ Using `hiddenValues` and setting the value to `['blue', 'purple', 'pink', 'brown
147154
Использование `multiple`:
148155
<FormField :options = "colors" type = "select" name = "multiple-color" multiple label = "Multiple colors" />
149156

157+
----
158+
159+
Использование `limit` = `2` вместе с `multiple`:
160+
<FormField :options = "colors" type = "select" name = "multiple-color" multiple label = "Multiple colors" limit = "2" />
161+
162+
150163
----
151164
The current state of the form:
152165

examples/input-select/App.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
<input-field type = "select" name = "language" :options = "languageOptions"/>
1111
<input-field type = "select" name = "languages" :options = "languageOptions" multiple label = "Multi languages"/>
1212
<input-field type = "select" name = "languages" :options = "languageOptions" multiple label = "Multi languages" disabled/>
13+
<input-field type = "select" name = "languages" :options = "languageOptions" multiple label = "Multi languages" limit = "2"/>
1314

1415

1516
<input-field type= "select" name="programming-language" :options = "programLanguageOptions" :hidden-values = "['2','1']"/>

src/utils/toggle-value-from-array.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,14 @@
33
* Help with splicing in any case.
44
* @param array
55
* @param value
6+
* @param limit Предельное число элементов в массиве.
67
*/
7-
export default function toggleValueFromArray<T>(array: T[], value: T) {
8+
export default function toggleValueFromArray<T>(array: T[], value: T, limit?: number) {
89
const index = array.indexOf(value);
9-
if (index === -1) array.push(value);
10+
if (index === -1) {
11+
if (limit === undefined || (typeof limit === 'number' && Number.isFinite(limit) && array.length < limit))
12+
array.push(value);
13+
}
1014
else array.splice(index, 1);
1115

1216
return array;

src/widgets/inputs/input-select/input-select.vue

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,8 @@ const props = defineProps<{
6969
placeholder?: string,
7070
errors: string[],
7171
hiddenValues?: OptionRow['value'][],
72-
multiple?: boolean
72+
multiple?: boolean,
73+
limit?: number | string
7374
}>()
7475
const emit = defineEmits<{
7576
(e: 'update:modelValue', v: any): void
@@ -162,9 +163,12 @@ function handleSelect(value: any) {
162163
if (!props.multiple) setActive(false)
163164
}
164165
function onInput(value: any) {
166+
165167
if (props.disabled) return;
166168
167-
const resultValue = props.multiple ? toggleValueFromArray(Array.isArray(props.modelValue) ? props.modelValue : [], value) : value
169+
const limit = typeof props.limit === 'number' ? props.limit : (typeof props.limit === 'string' ? Number.parseInt(props.limit, 10) : undefined);
170+
171+
const resultValue = props.multiple ? toggleValueFromArray(Array.isArray(props.modelValue) ? props.modelValue : [], value, limit) : value
168172
emit('update:modelValue', resultValue)
169173
}
170174

tests/integrations/inputs/input-select.spec.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,4 +263,21 @@ describe("Input Select Testing", () => {
263263

264264
expect(form.getValueByName(name)).toEqual([])
265265
})
266+
267+
test("Using limit should reject selecting more then provided in limit attr.", async () => {
268+
const wrap = defaultMount(defineSelectComponent({
269+
multiple: true,
270+
options: defaultOptions,
271+
limit: 2
272+
}))
273+
const form = (wrap.vm as any).form as Form;
274+
currentItem = wrap.find('.container-input-select-current')
275+
await currentItem.trigger('click');
276+
277+
await wrap.findAll('.input-select-option-list-item').reduce((acc, item) => {
278+
return acc.then(() => item.trigger('click'))
279+
}, Promise.resolve())
280+
281+
expect(form.getValueByName(name)).toEqual(defaultOptions.map(item => item.value).slice(0, 2))
282+
})
266283
})

0 commit comments

Comments
 (0)