twitter bootstrap typeahead (method 'toLowerCase' of undefined)

mmoscosa picture mmoscosa · Jun 28, 2012 · Viewed 24k times · Source

I am trying to use twitter bootstrap to get the manufacturers from my DB.

Because twitter bootstrap typeahead does not support ajax calls I am using this fork:

https://gist.github.com/1866577

In that page there is this comment that mentions how to do exactly what I want to do. The problem is when I run my code I keep on getting:

Uncaught TypeError: Cannot call method 'toLowerCase' of undefined

I googled around and came tried changing my jquery file to both using the minified and non minified as well as the one hosted on google code and I kept getting the same error.

My code currently is as follows:

$('#manufacturer').typeahead({
    source: function(typeahead, query){
        $.ajax({
            url: window.location.origin+"/bows/get_manufacturers.json",
            type: "POST",
            data: "",
            dataType: "JSON",
            async: false,
            success: function(results){
                var manufacturers = new Array;
                $.map(results.data.manufacturers, function(data, item){
                    var group;
                    group = {
                        manufacturer_id: data.Manufacturer.id,
                        manufacturer: data.Manufacturer.manufacturer
                    };
                    manufacturers.push(group);
                });
                typeahead.process(manufacturers);
            }
        });
    },
    property: 'name',
    items:11,
    onselect: function (obj) {

    }
});

on the url field I added the

window.location.origin

to avoid any problems as already discussed on another question

Also before I was using $.each() and then decided to use $.map() as recomended Tomislav Markovski in a similar question

Anyone has any idea why I keep getting this problem?!

Thank you

Answer

ThomasDurin picture ThomasDurin · Nov 1, 2012

Typeahead expect a list of string as source

$('#manufacturer').typeahead({
    source : ["item 1", "item 2", "item 3", "item 4"]
})

In your case you want to use it with a list of objects. This way you'll have to make some changes to make it works

This should works :

$('#manufacturer').typeahead({
    source: function(typeahead, query){
        $.ajax({
            url: window.location.origin+"/bows/get_manufacturers.json",
            type: "POST",
            data: "",
            dataType: "JSON",
            async: false,
            success: function(results){
                var manufacturers = new Array;
                $.map(results.data.manufacturers, function(data){
                    var group;
                    group = {
                        manufacturer_id: data.Manufacturer.id,
                        manufacturer: data.Manufacturer.manufacturer,

                        toString: function () {
                            return JSON.stringify(this);
                        },
                        toLowerCase: function () {
                            return this.manufacturer.toLowerCase();
                        },
                        indexOf: function (string) {
                            return String.prototype.indexOf.apply(this.manufacturer, arguments);
                        },
                        replace: function (string) {
                            return String.prototype.replace.apply(this.manufacturer, arguments);
                        }
                    };
                    manufacturers.push(group);
                });
                typeahead.process(manufacturers);
            }
        });
    },
    property: 'manufacturer',
    items:11,
    onselect: function (obj) {
        var obj = JSON.parse(obj);

        // You still can use the manufacturer_id here 
        console.log(obj.manufacturer_id);

        return obj.manufacturer;
    }
});