Twitter Bootstrap Typeahead(未定义的方法'toLowerCase')

22

我正在尝试使用Twitter Bootstrap从我的数据库获取制造商。

由于Twitter Bootstrap的typeahead不支持AJAX调用,因此我正在使用此分支:

https://gist.github.com/1866577

在那个页面中,有这个评论提到了如何做到我想要做的事情。问题是当我运行我的代码时,我一直得到:

Uncaught TypeError: Cannot call method 'toLowerCase' of undefined

我在谷歌上搜索并尝试更改我的jquery文件,包括使用最小化和非最小化以及托管在Google Code上的文件,但我仍然收到相同的错误。

我的代码目前如下:

$('#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) {

    }
});

在URL字段中,我添加了

window.location.origin

以避免像另一个问题中已经讨论过的任何问题。

此外,在使用$.each()之前,我决定像Tomislav Markovski在类似的问题中建议的那样改用$.map().

有人知道我为什么会一直遇到这个问题吗?!

谢谢


你是否尝试使用Firebug或IE的F12开发者工具来调试JavaScript代码,以找出它正在尝试调用toLowerCase()的确切位置? - Cᴏʀʏ
@Cory 使用 Google Chrome 检查工具,我发现错误出现在 Twitter Bootstrap 代码的第1664行。这相当于fork上的第124行。 - mmoscosa
在Chrome开发者工具中,许多JavaScript错误都有一个下拉菜单,其中包含其他错误,其中一个错误是您的代码中出现该错误的行。该错误与Bootstrap中的某些内容相关联,但实际上出现错误的地方是在您自己的代码中。 - Kevin Beal
9个回答

10

输入提示(Typeahead)需要一个字符串列表作为数据源。

$('#manufacturer').typeahead({
    source : ["item 1", "item 2", "item 3", "item 4"]
})
在您的情况下,您希望将其与对象列表一起使用。这样,您将需要进行一些更改使其起作用。
这应该可以工作:
$('#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;
    }
});

在进行了两处更正后,它终于起作用了。将 function(typeahead, query) 改为 (query, typehead);将 typeahead.process(manufacturers) 改为 typeahead(manufacturers)。如果我有误,请纠正我。 - nizam.sp

8
在我的情况下,我遇到了这个确切的错误,并且结果是我所使用的Bootstrap版本(2.0.4)不支持将函数传递给“source”设置。将版本升级到2.1.1可以解决问题。

我正在使用bootstrap v3.1.1,我遇到了相同的问题。 - Alexandre Bourlier

6

更新/修订问题: 当我在使用不支持 AJAX 的 Bootstrap 中使用原始的 Typeahead 扩展时,您提到的错误“Cannot call method 'toLowerCase' of undefined”发生了。 (正如您所发现的那样)你确定是没有加载原始的typeahead扩展而不是你修改后的扩展吗?

我已经成功地使用了这个 typeahead Gist ,它是您提到的类型的微小变化。一旦我切换到该 Gist 并确认输入数据良好(测试输入是否为 JS 对象中的字符串数组),问题就解决了。

希望这可以帮助到您。


原始答案:

错误发生的原因是传递到 typeahead 匹配函数的值未定义。这只是实际问题的副作用,该问题发生在您的输入和匹配函数之间的某个地方。 我怀疑“manufacturers”数组存在问题。首先测试以验证您拥有有效的数组。

// It appears your array constructor is missing ()
// try the following in your binding code:
var manufacturers = new Array();

这是我用来绑定输入到typeahead的内容。我确认它可以与你修改过的typeahead fork一起使用。

我的HTML代码:

<!-- Load bootstrap styles -->
<link href="bootstrap.css" rel="stylesheet" type="text/css" />
...

<input type="text" class="typeahead" name="Category" id="Category" maxlength="100" value="" />

...
<!-- and load jQuery and bootstrap with modified typeahead AJAX code -->
<script src="jquery-1.7.2.min.js" type="text/javascript"></script>
<script src="bootstrap-modified-typeahead.js" type="text/javascript"></script>

我的绑定JavaScript代码:

// Matches the desired text input ID in the HTML
var $TypeaheadInput = $("#Category");  

// Modify this path to your JSON source URL
// this source should return a JSON string array like the following:
// string[] result = {"test", "test2", "test3", "test4"}
var JsonProviderUrl = "../CategorySearch";

// Bind the input to the typeahead extension
$TypeaheadInput.typeahead({
    source: function (typeahead, query) {
        return $.post(JsonProviderUrl, { query: query }, function (data) {
            return typeahead.process(data);
        });
    }
});

“new Array” 是有效的简写。如果您不向构造函数提供参数,则 JavaScript 不需要括号。 - Dennis
我对数组的看法已经改正。我正在寻找可能导致数据未定义的原因......我无法复制特定数据源,所以我不确定是否存在其他不匹配。我认为typeahead代码不是问题,因为它在我的电脑上可以工作。 - Dan Sorensen
我通过调整js脚本(bootstrap,jquery和typeahed)的加载顺序解决了“无法调用未定义的'toLowerCase'方法”的问题。 - javanna

2
在我的情况下,源数组中存在空值导致了这个错误。
举个例子:
source : ["item 1", "item 2", null, "item 4"]

1
您的制造商对象没有“名称”属性,您应该进行更改。
property: 'name',

property: 'manufacturer',

1

您是否尝试过使用映射变量,例如下面的示例,当您的对象中有多个属性时,需要使用此功能;

source: function (query, process) {
        states = [];
        map = {};

        var data = [
            {"stateCode": "CA", "stateName": "California"},
            {"stateCode": "AZ", "stateName": "Arizona"},
            {"stateCode": "NY", "stateName": "New York"},
            {"stateCode": "NV", "stateName": "Nevada"},
            {"stateCode": "OH", "stateName": "Ohio"}
        ];

        $.each(data, function (i, state) {
            map[state.stateName] = state;
            states.push(state.stateName);
        });

        process(states);
    }

0

尝试这段代码:

String.prototype.hashCode = function(){
var hash = 0;
if (this.length == 0) return hash;
for (i = 0; i < this.length; i++) {
    char = this.charCodeAt(i);
    hash = ((hash<<5)-hash)+char;
    hash = hash & hash; // Convert to 32bit integer
}
return hash;
};

var map_manufacter, result_manufacters;
$('#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){

            result_manufacter = [], map_manufacters = {};
            $.each(results.data.manufacturers, function(item, data){                    
                map_manufacters[data.Manufacturer.manufacturer.hashCode()] = data;
                result_manufacters.push(data.Manufacter.manufacter);
            });             
            typeahead.process(result_manufacters);                
        }
    });
},
property: 'name',
items:11,
onselect: function (obj) {
    var hc = obj.hashCode();
    console.log(map_manufacter[hc]);
}

});


0

0

我之前遇到过这个问题。我建议您重新检查包含typeahead库的配置(通过main.js、app.js或config.js)。

否则,您可以将最新的Bootstrap版本覆盖到您的应用程序库中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接