0
# Search and Filtering
1
2
Built-in search functionality with customizable filtering logic, supporting real-time option filtering and custom match algorithms.
3
4
## Capabilities
5
6
### Search Configuration
7
8
Properties that control search input behavior and appearance.
9
10
```javascript { .api }
11
/**
12
* Enable/disable search input functionality
13
*/
14
searchable: Boolean // default: true
15
16
/**
17
* Clear search text when an option is selected
18
*/
19
clearSearchOnSelect: Boolean // default: true
20
21
/**
22
* Function to determine if search should clear on blur
23
* Returns true when single selection and clearSearchOnSelect is true
24
*/
25
clearSearchOnBlur: Function
26
27
/**
28
* Query selector for finding search input in custom search slot
29
*/
30
searchInputQuerySelector: String // default: '[type=search]'
31
```
32
33
### Filtering System
34
35
Advanced filtering configuration for customizing how options are matched against search text.
36
37
```javascript { .api }
38
/**
39
* Enable/disable filtering options by search text
40
* Should not be used with taggable
41
*/
42
filterable: Boolean // default: true
43
44
/**
45
* Custom filter matching logic for individual options
46
* @param option - The option to test
47
* @param label - The option's label text
48
* @param search - Current search text
49
* @returns Whether option matches search
50
*/
51
filterBy: Function // default: case-insensitive indexOf
52
53
/**
54
* Complete filter implementation for option lists
55
* @param options - Array of all options
56
* @param search - Current search text
57
* @returns Filtered array of options
58
*/
59
filter: Function // default: loops through options using filterBy
60
```
61
62
### Search State
63
64
Data properties and computed values that track search state.
65
66
```javascript { .api }
67
// Data properties
68
data: {
69
/**
70
* Current search input value
71
*/
72
search: String, // default: ''
73
74
/**
75
* Whether user is currently composing text (IME input)
76
*/
77
isComposing: Boolean // default: false
78
}
79
80
// Computed properties
81
computed: {
82
/**
83
* Whether search input has a non-empty value
84
*/
85
searching: Boolean,
86
87
/**
88
* Computed placeholder text for search input
89
*/
90
searchPlaceholder: String | undefined,
91
92
/**
93
* Options filtered by search text and including taggable options
94
*/
95
filteredOptions: Array,
96
97
/**
98
* Reference to the search input DOM element
99
*/
100
searchEl: HTMLInputElement
101
}
102
```
103
104
### Search Events
105
106
Events related to search input interactions.
107
108
```javascript { .api }
109
/**
110
* Emitted when search input gains focus
111
*/
112
'search:focus': () => void
113
114
/**
115
* Emitted when search input loses focus
116
*/
117
'search:blur': () => void
118
119
/**
120
* Emitted when search text changes (from ajax mixin)
121
* Provides search text and loading toggle function for AJAX
122
* @param searchText - Current search input value
123
* @param toggleLoading - Function to toggle loading state
124
*/
125
'search': (searchText: String, toggleLoading: Function) => void
126
```
127
128
### Search Methods
129
130
Methods for managing search input state and focus.
131
132
```javascript { .api }
133
/**
134
* Handle search input focus - opens dropdown
135
*/
136
onSearchFocus(): void
137
138
/**
139
* Handle search input blur - closes dropdown
140
*/
141
onSearchBlur(): void
142
143
/**
144
* Handle search input keydown events
145
* @param e - Keyboard event
146
* @returns Keydown handler function
147
*/
148
onSearchKeyDown(e: KeyboardEvent): Function
149
150
/**
151
* Handle search input keypress events
152
* @param e - Keyboard event
153
*/
154
onSearchKeyPress(e: KeyboardEvent): void
155
```
156
157
## Usage Examples
158
159
### Basic Search
160
161
```vue
162
<template>
163
<v-select
164
v-model="selected"
165
:options="options"
166
searchable
167
placeholder="Search options..."
168
/>
169
</template>
170
171
<script>
172
export default {
173
data() {
174
return {
175
selected: null,
176
options: [
177
'Apple', 'Banana', 'Cherry', 'Date', 'Elderberry',
178
'Fig', 'Grape', 'Honeydew', 'Kiwi', 'Lemon'
179
]
180
};
181
}
182
};
183
</script>
184
```
185
186
### Custom Filter Logic
187
188
```vue
189
<template>
190
<v-select
191
v-model="selected"
192
:options="products"
193
:filterBy="customFilter"
194
label="name"
195
placeholder="Search products..."
196
/>
197
</template>
198
199
<script>
200
export default {
201
data() {
202
return {
203
selected: null,
204
products: [
205
{ id: 1, name: 'MacBook Pro', category: 'Electronics', price: 1999 },
206
{ id: 2, name: 'iPhone 13', category: 'Electronics', price: 799 },
207
{ id: 3, name: 'Nike Air Max', category: 'Shoes', price: 120 }
208
]
209
};
210
},
211
methods: {
212
customFilter(option, label, search) {
213
// Search in name, category, and price
214
const searchLower = search.toLowerCase();
215
return (
216
option.name.toLowerCase().includes(searchLower) ||
217
option.category.toLowerCase().includes(searchLower) ||
218
option.price.toString().includes(search)
219
);
220
}
221
}
222
};
223
</script>
224
```
225
226
### Complete Custom Filter Implementation
227
228
```vue
229
<template>
230
<v-select
231
v-model="selected"
232
:options="users"
233
:filter="customFilterImplementation"
234
label="displayName"
235
placeholder="Advanced user search..."
236
/>
237
</template>
238
239
<script>
240
export default {
241
data() {
242
return {
243
selected: null,
244
users: [
245
{ id: 1, firstName: 'John', lastName: 'Doe', email: 'john@example.com' },
246
{ id: 2, firstName: 'Jane', lastName: 'Smith', email: 'jane@example.com' },
247
{ id: 3, firstName: 'Bob', lastName: 'Johnson', email: 'bob@example.com' }
248
]
249
};
250
},
251
computed: {
252
usersWithDisplayName() {
253
return this.users.map(user => ({
254
...user,
255
displayName: `${user.firstName} ${user.lastName}`
256
}));
257
}
258
},
259
methods: {
260
customFilterImplementation(options, search) {
261
if (!search) return options;
262
263
const searchTerms = search.toLowerCase().split(' ');
264
265
return options.filter(user => {
266
const searchableText = `${user.firstName} ${user.lastName} ${user.email}`.toLowerCase();
267
return searchTerms.every(term => searchableText.includes(term));
268
});
269
}
270
}
271
};
272
</script>
273
```
274
275
### AJAX Search Integration
276
277
```vue
278
<template>
279
<v-select
280
v-model="selected"
281
:options="searchResults"
282
:loading="isLoading"
283
@search="onSearch"
284
label="title"
285
placeholder="Search GitHub repositories..."
286
/>
287
</template>
288
289
<script>
290
import axios from 'axios';
291
292
export default {
293
data() {
294
return {
295
selected: null,
296
searchResults: [],
297
isLoading: false
298
};
299
},
300
methods: {
301
async onSearch(search, toggleLoading) {
302
if (search.length < 2) {
303
this.searchResults = [];
304
return;
305
}
306
307
toggleLoading(true);
308
309
try {
310
const response = await axios.get('https://api.github.com/search/repositories', {
311
params: { q: search, sort: 'stars', order: 'desc' }
312
});
313
this.searchResults = response.data.items.slice(0, 10);
314
} catch (error) {
315
console.error('Search error:', error);
316
this.searchResults = [];
317
} finally {
318
toggleLoading(false);
319
}
320
}
321
}
322
};
323
</script>
324
```
325
326
### Search State Control
327
328
```vue
329
<template>
330
<div>
331
<v-select
332
v-model="selected"
333
:options="options"
334
:clearSearchOnSelect="false"
335
ref="vSelect"
336
placeholder="Search with persistent text..."
337
/>
338
<button @click="clearSearch">Clear Search</button>
339
<button @click="focusSearch">Focus Search</button>
340
<p>Current search: "{{ currentSearch }}"</p>
341
</div>
342
</template>
343
344
<script>
345
export default {
346
data() {
347
return {
348
selected: null,
349
options: ['Apple', 'Banana', 'Cherry', 'Date', 'Elderberry'],
350
currentSearch: ''
351
};
352
},
353
watch: {
354
'$refs.vSelect.search'(newSearch) {
355
this.currentSearch = newSearch;
356
}
357
},
358
methods: {
359
clearSearch() {
360
this.$refs.vSelect.search = '';
361
},
362
focusSearch() {
363
this.$refs.vSelect.searchEl.focus();
364
}
365
}
366
};
367
</script>
368
```
369
370
### Non-Filterable Search (Display Only)
371
372
```vue
373
<template>
374
<v-select
375
v-model="selected"
376
:options="allOptions"
377
:filterable="false"
378
searchable
379
@search="onSearch"
380
placeholder="Search triggers external action..."
381
/>
382
</template>
383
384
<script>
385
export default {
386
data() {
387
return {
388
selected: null,
389
allOptions: ['Static Option 1', 'Static Option 2', 'Static Option 3']
390
};
391
},
392
methods: {
393
onSearch(searchText) {
394
// Handle search without filtering options
395
// Useful for AJAX search where server handles filtering
396
console.log('Search triggered:', searchText);
397
// Could trigger external API call, analytics, etc.
398
}
399
}
400
};
401
</script>
402
```