-
Notifications
You must be signed in to change notification settings - Fork 0
/
SelectWrapper.vue
101 lines (89 loc) · 3.52 KB
/
SelectWrapper.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
<template>
<select v-model="localValue"
@input="handleInput"
:autocomplete="autocomplete"
:autofocus="autofocus"
:class="['form-control', fieldSize ? 'form-control-' + fieldSize : '']"
:disabled="disabled"
:form="form"
:id="id"
:inputmode="inputmode"
:multiple="multiple"
:name="id"
:required="required"
:size="size"
:spellcheck="spellcheck"
:tabindex="tabindex"
:value="value">
<option :value="null" disabled v-if="!multiple && !initialSelection">
<slot name="placeholder" v-if="!multiple && !initialSelection">{{ $t('form.placeholder.select') }}</slot>
</option>
<slot></slot>
<template v-for="option in options">
<option v-if="isOpt(option)"
:disabled="option.disabled"
:key="option.value"
:value="option.value">{{ option.text }}</option>
<optgroup v-if="isOptGroup(option)"
:disabled="option.disabled"
:key="option.value"
:label="option.label">
<option v-for="option in option.options"
:disabled="option.disabled"
:key="option.value"
:value="option.value">{{ option.text }}</option>
</optgroup>
</template>
</select>
</template>
<script lang="ts">
import { Component, Mixins, Prop, Watch } from 'vue-property-decorator';
import { OptGroupInterface as OptGroup } from '@/interfaces/OptGroupInterface';
import { OptInterface as Opt } from '@/interfaces/OptInterface';
import { Options } from '@/types/Options';
import { SelectChild } from '@/types/SelectChild';
import MultipleMixin from '@/mixins/form/MultipleMixin';
import RequiredMixin from '@/mixins/form/RequiredMixin';
import SharedMixin from '@/mixins/form/SharedMixin';
@Component({})
export default class SelectWrapper extends Mixins(MultipleMixin, RequiredMixin, SharedMixin) {
@Prop({ default: null }) readonly options!: Options;
@Prop({ default: 0 }) readonly size!: number;
initialSelection: boolean = false;
localValue: string|number|boolean|object|null|Array<string|number|boolean|object> = this.value;
handleInput (event: InputEvent) {
const { target } = event;
if (target === null || !(target instanceof HTMLSelectElement)) {
return;
}
/* istanbul ignore next */
const selected = Array.from(target.options)
.filter((opt: HTMLOptionElement) => opt.selected)
.map((opt: HTMLOptionElement) => ('_value' in opt ? (opt as any)._value : opt.value));
this.localValue = target.multiple ? selected : selected[0];
}
isOpt (option: SelectChild): option is Opt {
return (option as Opt).value !== undefined;
}
isOptGroup (option: SelectChild): option is OptGroup {
return (option as OptGroup).options !== undefined;
}
mounted () {
// Check if an initial value is selected
this.initialSelection = !(this.value === '' ||
(this.value !== null && typeof this.value === 'object' && Object.keys(this.value).length < 1));
// If no initial value is set,
if (!this.initialSelection && !this.multiple) {
this.localValue = this.$el.firstChild!.nodeValue;
}
}
@Watch('localValue')
onLocalValueUpdate (val: string|number|boolean|object|null|Array<string|number|boolean|object>): void {
this.$emit('input', this.localValue);
}
@Watch('value')
onValueUpdate (val: string|number|boolean|object|null|Array<string|number|boolean|object>): void {
this.localValue = val;
}
}
</script>