or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

ajax-loading.mdcustomization.mdindex.mdkeyboard-navigation.mdsearch-filtering.mdselection.mdtagging.md

tagging.mddocs/

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

```