Skip to content

Commit 907b3fe

Browse files
committed
feat: add multiple attr, update title and select handler.
1 parent 691210e commit 907b3fe

File tree

4 files changed

+72
-12
lines changed

4 files changed

+72
-12
lines changed

docs/inputs/input-select.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,12 @@ If this array is specified, then the selection will not contain the elements spe
5151

5252
If no value is selected, a text label is shown.
5353

54+
### multiple <Badge type = "info">Optional</Badge>
55+
56+
- Type `boolean`
57+
58+
Данный параметр позволяет использовать множественную выборку. В таком случае modelValue будет обрабатываться как массив.
59+
5460
____
5561

5662
Also, all parameters common to all `FormField`. Information about them can be viewed
@@ -60,7 +66,8 @@ on [this page](./form-field.md#params).
6066
## Value
6167

6268
On clicking or selecting the corresponding `select` element, the value will be set to
63-
according to the value in the `value` field of the passed `options`.
69+
according to the value in the `value` field of the passed `options`. Если установлен атрибут `multiple`, то значение
70+
будет проверяться на наличие в modelValue: если не было найдено, то будет добавлено, иначе - исключено.
6471

6572
## Specification
6673

@@ -73,6 +80,8 @@ according to the value in the `value` field of the passed `options`.
7380
- An additional search controller is shown for a long list.
7481
- Blocking fields cancels navigation using `Tab`. There is also a change in the style of `select`.
7582
- If the validation fails, the field should change the style of the `select`.
83+
- При использовании аттрибута `multiple` выборка не должна закрывать выпадающий список.
84+
7685

7786
## Examples
7887

@@ -133,6 +142,10 @@ ____
133142
Using `hiddenValues` and setting the value to `['blue', 'purple', 'pink', 'brown', 'grey']`:
134143
<FormField :options = "colors" hiddenValues = "['blue', 'purple', 'pink', 'brown', 'grey']" type = "select" name = "color" label = "Filtered colors" />
135144

145+
----
146+
147+
Использование `multiple`:
148+
<FormField :options = "colors" type = "select" name = "multiple-color" multiple label = "Multiple colors" />
136149

137150
----
138151
The current state of the form:

examples/input-select/App.vue

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,13 @@
88
<div class="wrap-app ">
99
<input-field type="select" name = "sex" :options = "sexOptions"/>
1010
<input-field type = "select" name = "language" :options = "languageOptions"/>
11+
<input-field type = "select" name = "languages" :options = "languageOptions" multiple label = "Multi languages"/>
12+
<input-field type = "select" name = "languages" :options = "languageOptions" multiple label = "Multi languages" disabled/>
1113

1214

1315
<input-field type= "select" name="programming-language" :options = "programLanguageOptions" :hidden-values = "['2','1']"/>
1416
<input-field type = "select" name = "year" :options = "yearOptions" label = "Year"/>
17+
<input-field type = "select" name = "year" :options = "yearOptions" label = "Year"/>
1518

1619
<button class="button" @click="form.cleanValues()">Clean Form</button>
1720
</div>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/**
2+
* @description The method is used to add an element to the array if it does not exist, and to remove an element from the array when
3+
* Help with splicing in any case.
4+
* @param array
5+
* @param value
6+
*/
7+
export default function toggleValueFromArray<T>(array: T[], value: T) {
8+
const index = array.indexOf(value);
9+
if (index === -1) array.push(value);
10+
else array.splice(index, 1);
11+
12+
return array;
13+
}

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

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
'input-select_error': errors.length,
88
'input-select_active': isActive
99
}"
10-
:tabindex="!disabled ? 0 : 'none'"
10+
:tabindex="!disabled ? 0 : 'none' "
1111

1212
@focusout = "deactivate()"
1313
@keyup.enter="setActive()"
@@ -34,11 +34,11 @@
3434
<p
3535
v-for = "option in filteredOptions"
3636
:key = "option.value"
37-
:class="{'input-select-option-list-item_active': modelValue === option.value}"
37+
:class="{'input-select-option-list-item_active': isActiveItem(option.value)}"
3838
class="input-select-option-list-item"
3939
:title = "option.value"
4040

41-
@click = "onInput(option.value), setActive(false)"
41+
@click = "handleSelect(option.value)"
4242
>{{getLabelFromOptionRow(option)}}</p>
4343
</div>
4444

@@ -59,6 +59,7 @@ import getLabelFromOptionRow from "../../../utils/get-label-from-option-row";
5959
import FieldWrap from "../field-wrap.vue";
6060
import debounce from "../../../utils/debounce";
6161
import store from "../../../config/store";
62+
import toggleValueFromArray from "../../../utils/toggle-value-from-array";
6263
6364
const props = defineProps<{
6465
label?: string,
@@ -67,7 +68,8 @@ const props = defineProps<{
6768
options: OptionRow[],
6869
placeholder?: string,
6970
errors: string[],
70-
hiddenValues?: OptionRow['value'][]
71+
hiddenValues?: OptionRow['value'][],
72+
multiple?: boolean
7173
}>()
7274
const emit = defineEmits<{
7375
(e: 'update:modelValue', v: any): void
@@ -87,16 +89,23 @@ function setActive(v = !isActive.value) {
8789
if (!v) filter.value = '';
8890
if (v) nextTick(scrollToActiveItem.bind(null,'auto'))
8991
}
90-
function onInput(v: any) {
91-
if (props.disabled) return;
92-
emit('update:modelValue', v)
93-
}
92+
9493
/**
95-
* @description Метка отображаемая в поле.
94+
* @description Метка отображаемая в поле. В случае с одиночной выборкой отображается либо текущий элемент, либо placeholder.
95+
* В случае множественной выборки (multiple) - отображается первый выбранный элемент. Если элементов больше одного,
96+
* то отображается ещё + N, где N - количество выбранных элементов - 1
9697
* */
9798
const inputTitle = computed(() => {
98-
const selected = props.options.find(x => x.value === props.modelValue);
99-
if (selected) return getLabelFromOptionRow(selected);
99+
100+
const value = props.multiple ? props.modelValue?.[0] : props.modelValue;
101+
102+
const selected = props.options.find(x => x.value === value);
103+
if (selected) {
104+
const resultLabel = getLabelFromOptionRow(selected);
105+
if (!props.multiple) return resultLabel;
106+
107+
return resultLabel + (props.modelValue.length > 1 ? ` + ${props.modelValue.length - 1}` : '')
108+
}
100109
101110
return props.disabled ? '' : props.placeholder || '';
102111
})
@@ -145,6 +154,27 @@ const filteredOptions = computed(() => {
145154
)
146155
})
147156
157+
/**
158+
* @description Wrapper over data input.
159+
*/
160+
function handleSelect(value: any) {
161+
onInput(value);
162+
if (!props.multiple) setActive(false)
163+
}
164+
function onInput(value: any) {
165+
if (props.disabled) return;
166+
167+
const resultValue = props.multiple ? toggleValueFromArray(Array.isArray(props.modelValue) ? props.modelValue : [], value) : value
168+
emit('update:modelValue', resultValue)
169+
}
170+
171+
/**
172+
* @description Является ли данный элемент активным(modelValue) содержит значение
173+
*/
174+
function isActiveItem(value: any) {
175+
return props.multiple ? (Array.isArray(props.modelValue) ? props.modelValue : []).includes(value) : props.modelValue === value
176+
}
177+
148178
</script>
149179

150180
<style scoped>
@@ -204,6 +234,7 @@ const filteredOptions = computed(() => {
204234
.input-select-option-list-item_active {
205235
background-color: #f4f4f4;
206236
border-radius: 3px;
237+
color: var(--vf-input-active);
207238
}
208239
.input-select-option-list {
209240
overflow: auto;

0 commit comments

Comments
 (0)