Tags
The Tags feature allows users to create new options dynamically as they type. Ideal for email fields, categories, tags, and user mentions.
Email Tags with Validation
Tags with email format validation and multiple selection:
View code
HTML
<select id="emails" multiple></select>
JavaScript
const emailsData = [
{ id: '1', text: 'joao@exemplo.com' },
{ id: '2', text: 'maria@exemplo.com' },
{ id: '3', text: 'pedro@exemplo.com' }
];
const emailsSelect = new VanillaSmartSelect('#emails', {
data: emailsData,
multiple: true,
placeholder: 'Digite emails...',
tags: true,
createTag: (params) => {
const term = params.term?.trim();
if (!term) return null;
// Email validation
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(term)) {
return null; // Invalid email
}
return {
id: term,
text: term
};
},
insertTag: (data, tag) => {
// Insert at the beginning
data.unshift(tag);
},
templateResult: (item) => {
if (item._isTag) {
return `<div style="font-weight: 500;">➕ Adicionar email: <strong>${item.text}</strong></div>`;
}
return `<div>📧 ${item.text}</div>`;
}
});
Custom Categories
Dynamic creation of categories with automatic formatting:
View code
HTML
<select id="categories" multiple></select>
JavaScript
const categoriesData = [
{ id: 'javascript', text: 'JavaScript' },
{ id: 'python', text: 'Python' },
{ id: 'css', text: 'CSS' },
{ id: 'html', text: 'HTML' }
];
const categoriesSelect = new VanillaSmartSelect('#categories', {
data: categoriesData,
multiple: true,
placeholder: 'Select or create categories...',
tags: true,
createTag: (params) => {
const term = params.term?.trim();
if (!term) return null;
// Convert to lowercase and replace spaces with hyphens
const id = term.toLowerCase().replace(/\s+/g, '-');
return {
id: id,
text: term
};
},
templateResult: (item) => {
if (item._isTag) {
return `<div style="font-weight: 500;">✨ Criar nova categoria: "${item.text}"</div>`;
}
return `<div>🏷️ ${item.text}</div>`;
},
templateSelection: (item) => {
return item.text;
}
});
Tags with Custom Validation
Tags with selection limit, alphanumeric validation and custom colors:
View code
HTML
<select id="custom-tags" multiple></select>
JavaScript
const customTagsData = [
{ id: 'important', text: 'important', color: '#dc3545' },
{ id: 'urgent', text: 'urgent', color: '#ffc107' },
{ id: 'bug', text: 'bug', color: '#6f42c1' },
{ id: 'feature', text: 'feature', color: '#28a745' }
];
const customTagsSelect = new VanillaSmartSelect('#custom-tags', {
data: customTagsData,
multiple: true,
placeholder: 'Type tags (alphanumeric)...',
tags: true,
maximumSelectionLength: 5,
createTag: (params) => {
const term = params.term?.trim();
if (!term) return null;
// Only alphanumeric characters and hyphens
const validTag = /^[a-zA-Z0-9-]+$/;
if (!validTag.test(term)) {
return null; // Invalid format
}
// Generate random color
const colors = ['#007bff', '#28a745', '#dc3545', '#ffc107', '#17a2b8', '#6f42c1'];
const randomColor = colors[Math.floor(Math.random() * colors.length)];
return {
id: term.toLowerCase(),
text: term.toLowerCase(),
color: randomColor
};
},
templateResult: (item) => {
if (item._isTag) {
return `<div style="font-weight: 500;">
<span style="font-size: 18px;">+</span> Criar tag: <strong>${item.text}</strong>
<div style="font-size: 11px; margin-top: 4px; color: #999;">Apenas letras, números e hífens</div>
</div>`;
}
return `<div>
<span style="display: inline-block; width: 12px; height: 12px; border-radius: 50%; background: ${item.color}; margin-right: 8px;"></span>
${item.text}
</div>`;
},
templateSelection: (item) => {
return `<span style="color: ${item.color}">🏷️ ${item.text}</span>`;
}
});
User Mentions (Single Select)
Mention system with @ for single selection:
View code
HTML
<select id="mentions"></select>
JavaScript
const mentionsData = [
{ id: 'john', text: '@john', name: 'John Doe' },
{ id: 'jane', text: '@jane', name: 'Jane Smith' },
{ id: 'bob', text: '@bob', name: 'Bob Johnson' }
];
const mentionsSelect = new VanillaSmartSelect('#mentions', {
data: mentionsData,
placeholder: 'Type @username...',
allowClear: true,
tags: true,
createTag: (params) => {
let term = params.term?.trim();
if (!term) return null;
// Ensure it starts with @
if (!term.startsWith('@')) {
term = '@' + term;
}
// Remove @ for the ID
const username = term.substring(1);
// Only alphanumeric and underscores
if (!/^[a-zA-Z0-9_]+$/.test(username)) {
return null;
}
return {
id: username,
text: term,
name: term // No real name for new users
};
},
templateResult: (item) => {
if (item._isTag) {
return `<div style="font-weight: 500;">
➕ Mencionar novo usuário: <strong>${item.text}</strong>
</div>`;
}
return `<div>
<div style="font-weight: 500;">${item.text}</div>
<div style="font-size: 12px; color: #666;">${item.name}</div>
</div>`;
},
templateSelection: (item) => {
return item.text;
}
});
Tags Configuration
Main Options
| Option | Type | Description |
|---|---|---|
tags |
Boolean | Enables dynamic tag creation |
createTag |
Function | Function that validates and creates new tag objects |
insertTag |
Function | Function that defines where to insert the new tag in the data array |
_isTag Property
When a tag is created dynamically, the object has the _isTag: true property. Use this in templateResult to display a different message during creation.
createTag Parameters
createTag: (params) => {
// params.term: text typed by the user
// Return null to reject the tag
if (/* validation failed */) {
return null;
}
// Return object with id and text to create the tag
return {
id: '...',
text: '...',
// ... other custom fields
};
}
✅ Usage Tips
- Use
createTagto validate format before creating the tag - Combine tags with
maximumSelectionLengthto limit selections - Use
insertTagto control the position of new tags - Add custom fields (like colors) to tag objects
- Tags can be used in single or multiple mode