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
102
103
104
105
106
107
108
109
110
|
<script>
import { GlListbox } from '@gitlab/ui';
import { __ } from '~/locale';
const MIN_ITEMS_COUNT_FOR_SEARCHING = 20;
export default {
i18n: {
noResultsText: __('No results found'),
},
components: {
GlListbox,
},
model: GlListbox.model,
props: {
name: {
type: String,
required: true,
},
defaultToggleText: {
type: String,
required: true,
},
selected: {
type: String,
required: false,
default: null,
},
items: {
type: GlListbox.props.items.type,
required: true,
},
},
data() {
return {
searchString: '',
};
},
computed: {
allOptions() {
const allOptions = [];
const getOptions = (options) => {
for (let i = 0; i < options.length; i += 1) {
const option = options[i];
if (option.options) {
getOptions(option.options);
} else {
allOptions.push(option);
}
}
};
getOptions(this.items);
return allOptions;
},
isGrouped() {
return this.items.some((item) => item.options !== undefined);
},
isSearchable() {
return this.allOptions.length > MIN_ITEMS_COUNT_FOR_SEARCHING;
},
filteredItems() {
const searchString = this.searchString.toLowerCase();
if (!searchString) {
return this.items;
}
if (this.isGrouped) {
return this.items
.map(({ text, options }) => {
return {
text,
options: options.filter((option) => option.text.toLowerCase().includes(searchString)),
};
})
.filter(({ options }) => options.length);
}
return this.items.filter((item) => item.text.toLowerCase().includes(searchString));
},
toggleText() {
return this.selected
? this.allOptions.find((option) => option.value === this.selected).text
: this.defaultToggleText;
},
},
methods: {
search(searchString) {
this.searchString = searchString;
},
},
};
</script>
<template>
<div>
<gl-listbox
:selected="selected"
:toggle-text="toggleText"
:items="filteredItems"
:searchable="isSearchable"
:no-results-text="$options.i18n.noResultsText"
@search="search"
@select="$emit($options.model.event, $event)"
/>
<input ref="input" type="hidden" :name="name" :value="selected" />
</div>
</template>
|