Documentation v1.0.2

Preview

Overview

Transforms an input field or a textarea into a Tags component, in an easy, customizable way, with great performance and small code footprint, exploded with features For full documentation please check the plugin's site.

Usage

Tagify's CSS and Javascript files are bundled in the global plugin bundles and globally included in all pages:
<link href="assets/plugins/global/plugins.bundle.css" rel="stylesheet" type="text/css"/>
<script src="assets/plugins/global/plugins.bundle.js"></script>

Initialization

  • Tagify's CSS is highly customized in sass/vendors/plugins/_tagify.scss SCSS file in order to use it as native component within the design system. The SCSS code is compiled into assets/plugins/global/plugins.bundle.css and globally included in all pages.
  • Tagify's Javascript is bundled in assets/plugins/global/plugins.bundle.js and globally included in all pages.

Basic

Basic example of Tagify attached to an input element:
// The DOM elements you wish to replace with Tagify
var input1 = document.querySelector("#kt_tagify_1");
var input2 = document.querySelector("#kt_tagify_2");

// Initialize Tagify components on the above inputs
new Tagify(input1);
new Tagify(input2);
<div class="mb-10">
    <label class="form-label">Default input style</label>
    <input class="form-control" value="tag1, tag2, tag3" id="kt_tagify_1"/>
</div>

<div class="mb-0">
    <label class="form-label">Solid background style</label>
    <input class="form-control form-control-solid" value="tag1, tag2, tag3" id="kt_tagify_2"/>
</div>

Countries With Flags

Initialize Tagify programmatically and control the country flags via Javascript.
var tagify = new Tagify(document.querySelector('#kt_tagify_country'), {
    delimiters: null,
    templates: {
        tag: function (tagData) {
            const countryPath = 'assets/media/flags/' + tagData.value.toLowerCase().replace(/\s+/g, '-') + '.svg';
            try {
                // _ESCAPE_START_
                return `<tag title='${tagData.value}' contenteditable='false' spellcheck="false" 
                    class='tagify__tag ${tagData.class ? tagData.class : ""}' ${this.getAttributes(tagData)}>
                        <x title='remove tag' class='tagify__tag__removeBtn'></x>
                        <div class="d-flex align-items-center">
                            ${tagData.code ?
                        `<img onerror="this.style.visibility = 'hidden'" class="w-25px rounded-circle me-2" src='${countryPath}' />` : ''
                    }
                            <span class='tagify__tag-text'>${tagData.value}</span>
                        </div>
                    </tag>`
                // _ESCAPE_END_
            }
            catch (err) { }
        },

        dropdownItem: function (tagData) {
            const countryPath = 'assets/media/flags/' + tagData.value.toLowerCase().replace(/\s+/g, '-') + '.svg';
            try {
                // _ESCAPE_START_
                return `<div ${this.getAttributes(tagData)} class='tagify__dropdown__item ${tagData.class ? tagData.class : ""}'>
                            <img onerror="this.style.visibility = 'hidden'" class="w-25px rounded-circle me-2"
                                    src='${countryPath}' />
                            <span>${tagData.value}</span>
                        </div>`
                // _ESCAPE_END_
            }
            catch (err) { }
        }
    },
    enforceWhitelist: true,
    whitelist: [
        { value: 'Argentina', code: 'AR' },
        { value: 'Australia', code: 'AU', searchBy: 'beach, sub-tropical' },
        { value: 'Austria', code: 'AT' },
        { value: 'Brazil', code: 'BR' },
        { value: 'China', code: 'CN' },
        { value: 'Egypt', code: 'EG' },
        { value: 'Finland', code: 'FI' },
        { value: 'France', code: 'FR' },
        { value: 'Germany', code: 'DE' },
        { value: 'Hong Kong', code: 'HK' },
        { value: 'Hungary', code: 'HU' },
        { value: 'Iceland', code: 'IS' },
        { value: 'India', code: 'IN' },
        { value: 'Indonesia', code: 'ID' },
        { value: 'Italy', code: 'IT' },
        { value: 'Jamaica', code: 'JM' },
        { value: 'Japan', code: 'JP' },
        { value: 'Jersey', code: 'JE' },
        { value: 'Luxembourg', code: 'LU' },
        { value: 'Mexico', code: 'MX' },
        { value: 'Netherlands', code: 'NL' },
        { value: 'New Zealand', code: 'NZ' },
        { value: 'Norway', code: 'NO' },
        { value: 'Philippines', code: 'PH' },
        { value: 'Singapore', code: 'SG' },
        { value: 'South Korea', code: 'KR' },
        { value: 'Sweden', code: 'SE' },
        { value: 'Switzerland', code: 'CH' },
        { value: 'Thailand', code: 'TH' },
        { value: 'Ukraine', code: 'UA' },
        { value: 'United Kingdom', code: 'GB' },
        { value: 'United States', code: 'US' },
        { value: 'Vietnam', code: 'VN' }
    ],
    dropdown: {
        enabled: 1, // suggest tags after a single character input
        classname: 'extra-properties' // custom class for the suggestions dropdown
    } // map tags' values to this property name, so this property will be the actual value and not the printed value on the screen
})

// add the first 2 tags and makes them readonly
var tagsToAdd = tagify.settings.whitelist.slice(0, 2);
tagify.addTags(tagsToAdd);
<label class="form-label">Country Tags</label>
<input class="form-control d-flex align-items-center" value="" id="kt_tagify_country" />

Users With Avatars

Initialize Tagify programmatically and control the user portraits and names via Javascript.
var inputElm = document.querySelector('#kt_tagify_users');

const usersList = [
    { value: 1, name: 'Emma Smith', avatar: 'avatars/300-6.jpg', email: 'e.smith@kpmg.com.au' },
    { value: 2, name: 'Max Smith', avatar: 'avatars/300-1.jpg', email: 'max@kt.com' },
    { value: 3, name: 'Sean Bean', avatar: 'avatars/300-5.jpg', email: 'sean@dellito.com' },
    { value: 4, name: 'Brian Cox', avatar: 'avatars/300-25.jpg', email: 'brian@exchange.com' },
    { value: 5, name: 'Francis Mitcham', avatar: 'avatars/300-9.jpg', email: 'f.mitcham@kpmg.com.au' },
    { value: 6, name: 'Dan Wilson', avatar: 'avatars/300-23.jpg', email: 'dam@consilting.com' },
    { value: 7, name: 'Ana Crown', avatar: 'avatars/300-12.jpg', email: 'ana.cf@limtel.com' },
    { value: 8, name: 'John Miller', avatar: 'avatars/300-13.jpg', email: 'miller@mapple.com' }
];

function tagTemplate(tagData) {
    return `
        <tag title="${(tagData.title || tagData.email)}"
                contenteditable='false'
                spellcheck='false'
                tabIndex="-1"
                class="${this.settings.classNames.tag} ${tagData.class ? tagData.class : ""}"
                ${this.getAttributes(tagData)}>
            <x title='' class='tagify__tag__removeBtn' role='button' aria-label='remove tag'></x>
            <div class="d-flex align-items-center">
                <div class='tagify__tag__avatar-wrap ps-0'>
                    <img onerror="this.style.visibility='hidden'" class="rounded-circle w-25px me-2" src="assets/media/${tagData.avatar}">
                </div>
                <span class='tagify__tag-text'>${tagData.name}</span>
            </div>
        </tag>
    `
}

function suggestionItemTemplate(tagData) {
    return `
        <div ${this.getAttributes(tagData)}
            class='tagify__dropdown__item d-flex align-items-center ${tagData.class ? tagData.class : ""}'
            tabindex="0"
            role="option">

            ${tagData.avatar ? `
                    <div class='tagify__dropdown__item__avatar-wrap me-2'>
                        <img onerror="this.style.visibility='hidden'"  class="rounded-circle w-50px me-2" src="assets/media/${tagData.avatar}">
                    </div>` : ''
                }

            <div class="d-flex flex-column">
                <strong>${tagData.name}</strong>
                <span>${tagData.email}</span>
            </div>
        </div>
    `
}

// initialize Tagify on the above input node reference
var tagify = new Tagify(inputElm, {
    tagTextProp: 'name', // very important since a custom template is used with this property as text. allows typing a "value" or a "name" to match input with whitelist
    enforceWhitelist: true,
    skipInvalid: true, // do not remporarily add invalid tags
    dropdown: {
        closeOnSelect: false,
        enabled: 0,
        classname: 'users-list',
        searchKeys: ['name', 'email']  // very important to set by which keys to search for suggesttions when typing
    },
    templates: {
        tag: tagTemplate,
        dropdownItem: suggestionItemTemplate
    },
    whitelist: usersList
})

tagify.on('dropdown:show dropdown:updated', onDropdownShow)
tagify.on('dropdown:select', onSelectSuggestion)

var addAllSuggestionsElm;

function onDropdownShow(e) {
    var dropdownContentElm = e.detail.tagify.DOM.dropdown.content;

    if (tagify.suggestedListItems.length > 1) {
        addAllSuggestionsElm = getAddAllSuggestionsElm();

        // insert "addAllSuggestionsElm" as the first element in the suggestions list
        dropdownContentElm.insertBefore(addAllSuggestionsElm, dropdownContentElm.firstChild)
    }
}

function onSelectSuggestion(e) {
    if (e.detail.elm == addAllSuggestionsElm)
        tagify.dropdown.selectAll.call(tagify);
}

// create a "add all" custom suggestion element every time the dropdown changes
function getAddAllSuggestionsElm() {
    // suggestions items should be based on "dropdownItem" template
    return tagify.parseTemplate('dropdownItem', [{
        class: "addAll",
        name: "Add all",
        email: tagify.settings.whitelist.reduce(function (remainingSuggestions, item) {
            return tagify.isTagDuplicate(item.value) ? remainingSuggestions : remainingSuggestions + 1
        }, 0) + " Members"
    }]
    )
}
<label class="form-label">User Tags</label>
<input class="form-control d-flex align-items-center" value="" placeholder="write some tags" id="kt_tagify_users" />

Sizes

Apply the standard Bootstrap input sizes .form-control-sm and .form-control-lg:
// The DOM elements you wish to replace with Tagify
var input1 = document.querySelector("#kt_tagify_3");
var input2 = document.querySelector("#kt_tagify_4");
var input2 = document.querySelector("#kt_tagify_5");

// Initialize Tagify components on the above inputs
new Tagify(input1);
new Tagify(input2);
new Tagify(input3);
<input class="form-control form-control-sm form-control-solid" placeholder="Enter tags" value="tag1, tag2, tag3" id="kt_tagify_3"/>
<input class="form-control form-control-solid" placeholder="Enter tags" value="tag1, tag2, tag3" id="kt_tagify_4"/>
<input class="form-control form-control-lg form-control-solid" placeholder="Enter tags" value="tag1, tag2, tag3" id="kt_tagify_5"/>

Suggestions

A dropdown with suggestions will appear immediately when Tagify has focus.
// The DOM elements you wish to replace with Tagify
var input = document.querySelector("#kt_tagify_6");
var input = document.querySelector("#kt_tagify_7");

// Initialize Tagify script on the above inputs
new Tagify(input, {
    whitelist: ["Ada", "Adenine", "Agda", "Agilent VEE"],
    maxTags: 10,
    dropdown: {
        maxItems: 20,           // <- mixumum allowed rendered suggestions
        classname: "tagify__inline__suggestions", // <- custom classname for this dropdown, so it could be targeted
        enabled: 0,             // <- show suggestions on focus
        closeOnSelect: false    // <- do not hide the suggestions dropdown once an item has been selected
    }
});

new Tagify(input, {
    whitelist: ["Ada", "Adenine", "Agda", "Agilent VEE"],
    maxTags: 10,
    dropdown: {
        maxItems: 20,           // <- mixumum allowed rendered suggestions
        classname: "", // <- custom classname for this dropdown, so it could be targeted
        enabled: 0,             // <- show suggestions on focus
        closeOnSelect: false    // <- do not hide the suggestions dropdown once an item has been selected
    }
});
<input class="form-control form-control-solid" value="css, html, javascript" id="kt_tagify_6"/>

<input class="form-control form-control-solid" value="css, html, javascript" id="kt_tagify_7"/>

External Suggestions

Allows to select suggestions from an external container.
Suggested: Bootstrap, Angular, React, Vue
var input = document.querySelector('#kt_tagify_custom'),

// Init Tagify script on the above inputs
tagify = new Tagify(input, {
    whitelist: ["Bootstrap", "Angular", "React", "Vue"],
    placeholder: "Type something",
    enforceWhitelist: true
});

// Suggestions
var suggestions = document.querySelector('#kt_tagify_custom_suggestions');

// Suggestion item click
KTUtil.on(suggestions,  '[data-kt-suggestion="true"]', 'click', function(e) {
    tagify.addTags([this.innerText]);
});
<div class="mb-0">
    <label class="form-label">External Suggestions</label>
    <input class="form-control form-control-solid" value="Bootstrap" id="kt_tagify_custom"/>
    <div class="pt-3">
        <span class="text-gray-700">Suggested:</span>
        
        <span class="text-danger" id="kt_tagify_custom_suggestions">
            <span class="cursor-pointer" data-kt-suggestion="true">Bootstrap</span>,
            <span class="cursor-pointer" data-kt-suggestion="true">Angular</span>,
            <span class="cursor-pointer" data-kt-suggestion="true">React</span>,
            <span class="cursor-pointer" data-kt-suggestion="true">Vue</span>
        </span>
    </div>
</div>

Readonly Mode

If the original input field has a readonly attribute, then, via CSS, there will be no way of manually adding tags because the inline contenteditable element will be hidden.
// The DOM elements you wish to replace with Tagify
var input1 = document.querySelector("#kt_tagify_8");

// Initialize Tagify components on the above inputs
new Tagify(input1);
<input class="form-control form-control-solid" value="css, html, javascript" readonly id="kt_tagify_8"/>
Preview Get Help Buy Now