'Bootstrap Tags Input on dynamically created elements

I use Bootstrap Tags Input (with typeahead) and it works great on my static inputs. But I also create dynamic input fields - these won't work.

How can I attach a dynamically created element to tagsinput?

Main code:

var depends = ["jquery"];
var substringMatcher = function(strs) {
    return function findMatches(q, cb) {
        var matches;
        matches = [];
        substrRegex = new RegExp(q, 'i');
        $.each(strs, function(i, str) {
            if (substrRegex.test(str)) {
                matches.push(str);
            }
        });
        cb(matches);
    };
};
var field = $('.resource_depend');
field.tagsinput({
    confirmKeys: [13, 44],
    itemValue: 'id',
    typeaheadjs:({
        hint: true,
        highlight: true,
        minLength: 1
    }, {
        name: 'depends',
        source: substringMatcher(depends)
    }),
    maxTags: 20,
    maxChars: 50
});

Later I have (something like):

...
var cnt = 0;
var addFragment = myStaticFragment.cloneNode(true);
addFragment.id = 'dynamic_'+ cnt
myStaticFragment.parentNode.appendChild(addFragment);
cnt += 1;

Note: I have several independent fields that use independent tags.

With the developer tools, it seems to add some code, but not the functionality like on the static inputs.

UPDATE: I tried to remove the "data-role" attribute from 'myStaticFragment' and call the main code upon each addition. It just doubled the input field without any difference.



Solution 1:[1]

I haven't used the typeahead library before, so this based on my experience with similar javascript UI libraries. If it's anything like the KendoUI or jQueryUI libraries, then you need to add the functionality AFTER the element is on the DOM.

So, since you use bits of jQuery further up the javascipt, I'll utilise that.

By changing this block:

var cnt = 0;
var addFragment = myStaticFragment.cloneNode(true);
addFragment.id = 'dynamic_'+ cnt
myStaticFragment.parentNode.appendChild(addFragment);
cnt += 1;

To (for example):

var cnt = 0;
var addFragment = $(myStaticFragment.cloneNode(true)).prop('id', 'dynamic_'+ cnt);
var tagFragment = $(myStaticFragment).data().tagsInput(); //retrieve the functionality of the element
myStaticFragment.parentNode.appendChild(addFragment); //add the fragment to the DOM
addFragment.tagsInput(tagFragment); 
cnt += 1;

Should, theoretically, at least point you far enough down the right tracks to be able to suss out the exact methodology that this particular library requires.

UPDATE: to account for older versions of jQuery that don't have the .data() function, one option may be to store the settings for the element in a variable. Something along the lines of:

var tagInputSettings = {
    confirmKeys: [13, 44],
    itemValue: 'id',
    typeaheadjs:({
        hint: true,
        highlight: true,
        minLength: 1
    }, {
        name: 'depends',
        source: substringMatcher(depends)
    }),
    maxTags: 20,
    maxChars: 50
};

var field = $('.resource_depend');
field.tagInput(tagInputSettings); 

........................

var cnt = 0;
var addFragment = $(myStaticFragment.cloneNode(true)).prop('id', 'dynamic_'+ cnt);
myStaticFragment.parentNode.appendChild(addFragment); //add the fragment to the DOM
addFragment.tagsInput(tagInputSettings); 
cnt += 1;

Might be of use?

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1