Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling objects with Twitter Bootstrap Typeahead

I'm using the Bootstrap Typeahead plugin like so:

$('#Organisation').typeahead({
            source: function (query, process) {
                return $.get(AppURL + 'Organisations/Manage/SearchByName/',
                {
                    term: query
                },
                function (data) {
                    var results = [];
                    var fullResults = [];
                    $.each(data, function (index, item) {
                        results.push(item.label);
                        fullResults.push({
                            id: item.ID,
                            label: item.label
                        });
                    });

                    return process(results);


                });
            },
            updater: function (selection) {
                $('#OrganisationID').val(selection);
            }
        });

I have two returned arrays, this is because Typeahead ONLY wants a list of strings instead of an object. The second array contains both the label and id.

Once a user selects an item from the list I need to get the ID from this selection and then use it to insert into a hidden field. But the selection will just be the name, as the ID can't be passed through via Typeahead.

Any ideas on how I can solve this?

An example of the two returned arrays:

results: ["Organisation 1","Organisation 2"]

fullResults: [{"label":"Organisation 1","ID":2},{"label":"Organisation 2","ID":1}]

like image 869
Cameron Avatar asked Apr 19 '13 13:04

Cameron


2 Answers

After searching around a bit on the net I found this HowTo. In it they do what you want, but with no ajax.

You should also be able to return a object, from the source function, but you would need to re-implement all the helper functions of typeahead.

like image 180
fredrik Avatar answered Sep 25 '22 13:09

fredrik


You cannot normally use JSON objects directly within Bootstrap Typeahead (2.x), but you can easily tweak it to do so. The wording of this question should help for people to find this in one place. Other questions have asked similar things, but not identical to the way that you did.

var typeahead = control.typeahead({ /* ... */ }).data('typeahead');

// manually override select and render
//  (change attr('data-value' ...) to data('value' ...))
//  otherwise both functions are exact copies
typeahead.select = function() {
    var val = this.$menu.find('.active').data('value')
    this.$element.val(this.updater(val)).change()
    return this.hide()
};
typeahead.render = function(items) {
    var that = this

    items = $(items).map(function (i, item) {
        i = $(that.options.item).data('value', item)
        i.find('a').html(that.highlighter(item))
        return i[0]
    });

    items.first().addClass('active')
    this.$menu.html(items)
    return this
};

Other than that, you must override highlighter, matcher, sorter, and updater, but those can done via the options passed into the typeahead, where the passed in item(s) are now your JSON objects.

When selecting items, updater is called, which is how you set the value and use the JSON data:

updater: function (item) {
    someGlobalValue = item.id;

    // must return a normal string; sets the textbox value
    return item.name;
}

This also means that you don't need to do anything fancy to associate, or otherwise "remember" the items external to Typeahead referenced example in the other answer. The most annoying part of the whole overriding process is rewriting the sorter in every use.

like image 38
pickypg Avatar answered Sep 26 '22 13:09

pickypg