0
# Tagging and Creation
1
2
Dynamic option creation functionality allowing users to create new options from search input, with customizable creation logic and tag management.
3
4
## Capabilities
5
6
### Tagging Configuration
7
8
Properties that enable and control option creation from user input.
9
10
```javascript { .api }
11
/**
12
* Enable/disable creating options from search input
13
* When true, allows users to create new options by typing
14
*/
15
taggable: Boolean // default: false
16
17
/**
18
* When true, newly created tags will be added to the options list
19
* Useful for persistent tag creation across sessions
20
*/
21
pushTags: Boolean // default: false
22
23
/**
24
* User-defined function for creating new options
25
* Determines format of created options
26
* @param option - The search text to convert to an option
27
* @returns Created option object or string
28
*/
29
createOption: Function // default: creates object with label key or returns string
30
```
31
32
### Tag State Management
33
34
Data properties that track created tags and their state.
35
36
```javascript { .api }
37
// Data properties
38
data: {
39
/**
40
* Array of tags that have been created when pushTags is enabled
41
*/
42
pushedTags: Array // default: []
43
}
44
45
// Computed properties
46
computed: {
47
/**
48
* Available options including pushed tags
49
* Combines original options with user-created tags
50
*/
51
optionList: Array
52
}
53
```
54
55
### Tag Creation Methods
56
57
Methods for creating, managing, and validating new tags.
58
59
```javascript { .api }
60
/**
61
* Add a created tag to the pushed tags list
62
* Called automatically when pushTags is true
63
* @param option - The tag option to add
64
*/
65
pushTag(option: Object | String): void
66
67
/**
68
* Check if an option already exists in the option list
69
* Prevents duplicate tag creation
70
* @param option - Option to check for existence
71
* @returns Whether the option exists
72
*/
73
optionExists(option: Object | String): Boolean
74
75
/**
76
* Delete value on Delete keypress when no text in search input
77
* Handles tag removal via keyboard in multiple selection mode
78
* @returns Deleted value or undefined
79
*/
80
maybeDeleteValue(): any
81
```
82
83
### Tag Events
84
85
Events emitted during tag creation and management.
86
87
```javascript { .api }
88
/**
89
* Emitted when a new tag/option is created from user input
90
* @param option - The newly created option
91
*/
92
'option:created': (option: Object | String) => void
93
```
94
95
## Usage Examples
96
97
### Basic Tagging
98
99
```vue
100
<template>
101
<v-select
102
v-model="selectedTags"
103
:options="availableTags"
104
taggable
105
multiple
106
placeholder="Type to create new tags..."
107
/>
108
</template>
109
110
<script>
111
export default {
112
data() {
113
return {
114
selectedTags: [],
115
availableTags: ['JavaScript', 'Vue.js', 'React', 'Angular']
116
};
117
}
118
};
119
</script>
120
```
121
122
### Persistent Tag Creation
123
124
```vue
125
<template>
126
<v-select
127
v-model="selectedCategories"
128
:options="categories"
129
taggable
130
pushTags
131
multiple
132
@option:created="onTagCreated"
133
placeholder="Add or create categories..."
134
/>
135
</template>
136
137
<script>
138
export default {
139
data() {
140
return {
141
selectedCategories: [],
142
categories: ['Electronics', 'Clothing', 'Books', 'Home & Garden']
143
};
144
},
145
methods: {
146
onTagCreated(newTag) {
147
console.log('New category created:', newTag);
148
// Could save to backend, analytics, etc.
149
}
150
}
151
};
152
</script>
153
```
154
155
### Custom Tag Creation Logic
156
157
```vue
158
<template>
159
<v-select
160
v-model="selectedUsers"
161
:options="users"
162
:createOption="createUserOption"
163
taggable
164
multiple
165
label="name"
166
placeholder="Add existing users or create new ones..."
167
/>
168
</template>
169
170
<script>
171
export default {
172
data() {
173
return {
174
selectedUsers: [],
175
users: [
176
{ id: 1, name: 'John Doe', email: 'john@example.com', type: 'existing' },
177
{ id: 2, name: 'Jane Smith', email: 'jane@example.com', type: 'existing' }
178
]
179
};
180
},
181
methods: {
182
createUserOption(inputText) {
183
// Create a user object from input text
184
const email = inputText.includes('@') ? inputText : `${inputText}@example.com`;
185
return {
186
id: Date.now(), // Temporary ID
187
name: inputText,
188
email: email,
189
type: 'new'
190
};
191
}
192
}
193
};
194
</script>
195
```
196
197
### Tag Validation and Formatting
198
199
```vue
200
<template>
201
<v-select
202
v-model="selectedSkills"
203
:options="skills"
204
:createOption="createSkillTag"
205
taggable
206
pushTags
207
multiple
208
@option:created="validateAndSaveSkill"
209
placeholder="Add skills (will be formatted)..."
210
/>
211
</template>
212
213
<script>
214
export default {
215
data() {
216
return {
217
selectedSkills: [],
218
skills: [
219
'JavaScript', 'Python', 'Java', 'C++', 'Go',
220
'React', 'Vue.js', 'Angular', 'Node.js'
221
]
222
};
223
},
224
methods: {
225
createSkillTag(skillText) {
226
// Format and validate skill name
227
const formattedSkill = skillText
228
.split(' ')
229
.map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
230
.join(' ');
231
232
return formattedSkill;
233
},
234
validateAndSaveSkill(skill) {
235
// Validate skill length
236
if (skill.length < 2) {
237
this.$nextTick(() => {
238
// Remove invalid skill
239
this.selectedSkills = this.selectedSkills.filter(s => s !== skill);
240
});
241
alert('Skill name must be at least 2 characters long');
242
return;
243
}
244
245
console.log('Valid skill created:', skill);
246
// Could save to backend
247
}
248
}
249
};
250
</script>
251
```
252
253
### Email Tag Creation
254
255
```vue
256
<template>
257
<v-select
258
v-model="selectedEmails"
259
:options="commonEmails"
260
:createOption="createEmailOption"
261
taggable
262
multiple
263
placeholder="Enter email addresses..."
264
/>
265
</template>
266
267
<script>
268
export default {
269
data() {
270
return {
271
selectedEmails: [],
272
commonEmails: [
273
'admin@example.com',
274
'support@example.com',
275
'info@example.com'
276
]
277
};
278
},
279
methods: {
280
createEmailOption(emailText) {
281
// Validate email format
282
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
283
284
if (emailRegex.test(emailText)) {
285
return emailText.toLowerCase();
286
} else {
287
// Return invalid marker or throw error
288
return null; // This will prevent tag creation
289
}
290
}
291
}
292
};
293
</script>
294
```
295
296
### Complex Object Tag Creation
297
298
```vue
299
<template>
300
<v-select
301
v-model="selectedTasks"
302
:options="existingTasks"
303
:createOption="createTaskOption"
304
taggable
305
pushTags
306
multiple
307
label="title"
308
:reduce="task => task.id"
309
placeholder="Add existing tasks or create new ones..."
310
/>
311
</template>
312
313
<script>
314
export default {
315
data() {
316
return {
317
selectedTasks: [],
318
existingTasks: [
319
{ id: 1, title: 'Review PR #123', priority: 'high', status: 'pending' },
320
{ id: 2, title: 'Update documentation', priority: 'medium', status: 'in-progress' }
321
]
322
};
323
},
324
methods: {
325
createTaskOption(taskTitle) {
326
// Create a task object with default values
327
return {
328
id: `temp-${Date.now()}`, // Temporary ID
329
title: taskTitle,
330
priority: 'medium',
331
status: 'pending',
332
createdAt: new Date().toISOString(),
333
createdBy: 'user'
334
};
335
}
336
}
337
};
338
</script>
339
```
340
341
### Conditional Tagging
342
343
```vue
344
<template>
345
<div>
346
<label>
347
<input type="checkbox" v-model="allowNewTags"> Allow creating new tags
348
</label>
349
350
<v-select
351
v-model="selectedTags"
352
:options="predefinedTags"
353
:taggable="allowNewTags"
354
multiple
355
:placeholder="allowNewTags ? 'Type to create tags...' : 'Choose from existing tags...'"
356
/>
357
</div>
358
</template>
359
360
<script>
361
export default {
362
data() {
363
return {
364
allowNewTags: false,
365
selectedTags: [],
366
predefinedTags: ['Tag 1', 'Tag 2', 'Tag 3', 'Tag 4']
367
};
368
}
369
};
370
</script>
371
```
372
373
### Tag Creation with Backend Integration
374
375
```vue
376
<template>
377
<v-select
378
v-model="selectedTopics"
379
:options="topics"
380
:createOption="createTopicOption"
381
taggable
382
pushTags
383
multiple
384
:loading="isCreatingTopic"
385
@option:created="saveNewTopic"
386
placeholder="Add or create discussion topics..."
387
/>
388
</template>
389
390
<script>
391
import axios from 'axios';
392
393
export default {
394
data() {
395
return {
396
selectedTopics: [],
397
topics: [],
398
isCreatingTopic: false
399
};
400
},
401
async created() {
402
// Load existing topics
403
try {
404
const response = await axios.get('/api/topics');
405
this.topics = response.data;
406
} catch (error) {
407
console.error('Failed to load topics:', error);
408
}
409
},
410
methods: {
411
createTopicOption(topicName) {
412
return {
413
id: null, // Will be set by backend
414
name: topicName,
415
isNew: true
416
};
417
},
418
async saveNewTopic(topic) {
419
if (!topic.isNew) return;
420
421
this.isCreatingTopic = true;
422
423
try {
424
const response = await axios.post('/api/topics', {
425
name: topic.name
426
});
427
428
// Update the topic with real ID from backend
429
const savedTopic = response.data;
430
const index = this.topics.findIndex(t => t === topic);
431
if (index > -1) {
432
this.$set(this.topics, index, savedTopic);
433
}
434
435
// Update selection if this topic was selected
436
const selectedIndex = this.selectedTopics.findIndex(t => t === topic);
437
if (selectedIndex > -1) {
438
this.$set(this.selectedTopics, selectedIndex, savedTopic);
439
}
440
441
} catch (error) {
442
console.error('Failed to save new topic:', error);
443
// Remove the failed topic
444
this.topics = this.topics.filter(t => t !== topic);
445
this.selectedTopics = this.selectedTopics.filter(t => t !== topic);
446
} finally {
447
this.isCreatingTopic = false;
448
}
449
}
450
}
451
};
452
</script>
453
```