javascriptjsontwitter-bootstrapbloodhoundbootstrap-tokenfield

Bootstrap tokenfield json with multiple fields


I have an issue with Bootstrap tokenfield when I'm using an Object with more than one field. For example, I get no issues when I use a json object is defined as:

local: [ { value: 'red' }, { value: 'orange' }} ]

The initializer for this is:

$('#tokenfield-input').tokenfield({
    typeahead: [null, { source: engine.ttAdapter(),
    displayKey: 'value',
    displayValue: 'value'
    }]
});

This works correctly. However, if I add another field, it throws an error Cannot read property 'toString' of undefined when the token is selected. The json is defined as:

local: [ { id: 1, value: 'red' }, { id: 2, value: 'orange' }} ]

The initializer for this is:

$('#tokenfield-input').tokenfield({
    typeahead: [null, { source: engine.ttAdapter(),
    displayKey: 'value',
    displayValue: 'id'
    }]
});

The fiddle here contains a live example. What would be the correct way to do this?


Solution

  • The reason it not working is because the format of the data passed to local is incorrect. Typeahead/bloodhound accepts an array of Objects with the fields value and suggestion, where value is the field that is to be search against and suggestion is the original object. Using the jQuery map function can transform the initial array (shown under local below).

    For the suggestions to load correctly, the suggestion template would need to be overridden.

    var one =  [
       { id: 1, name: 'red' },
       { id: 2, name: 'orange' },
       { id: 3, name: 'yellow' },
       { id: 4, name: 'green' },
       { id: 5, name: 'blue' },
       { id: 6, name: 'indigo' },
       { id: 7, name: 'violet' },
       { id: 8, name: 'black' },
       { id: 9, name: 'white' },
       { id: 10, name: 'brown' },
       { id: 11, name: 'pink' }
       ];
    
       $(document).ready(function () {
                var engine = new Bloodhound({
                local: $.map(one, function(d) {
                   return {value: d.name, suggestion: d}
                   }),
                    datumTokenizer: function (d) {
                        return Bloodhound.tokenizers.whitespace(d.value);
                    },
                    queryTokenizer: Bloodhound.tokenizers.whitespace
                });
    
                engine.initialize();
    
                // Action item 1
                $('#mytokenfield').tokenfield({
                    typeahead: [null, {
                        source: engine.ttAdapter(),
                        displayKey: 'value',
                        templates: {
                           suggestion: function (data) {
                              return $("<div />", {
                              "html": "<br />" + "<span>" +
                              data.suggestion.ID + " " + data.suggestion.Name + "</span><br />"
                              })
                           }
                       }
                    }]
                });