Twitter bootstrap typeahead (метод 'toLowerCase' из undefined)
Я пытаюсь использовать twitter bootstrap, чтобы получить производителей из моей базы данных.
Поскольку twitter bootstrap typeahead не поддерживает вызовы ajax, я использую эту вилку:
https://gist.github.com/1866577
На этой странице есть comment, в котором упоминается, как делать именно то, что я хочу сделать. Проблема в том, что когда я запускаю свой код, я продолжаю получать:
Uncaught TypeError: невозможно вызвать метод 'toLowerCase' из undefined
Я столкнулся с ошибкой и попробовал сменить файл jquery на оба с использованием мини-и неминифицированных, а также на один, размещенный в коде google, и я продолжал получать ту же ошибку.
В настоящее время мой код выглядит следующим образом:
$('#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()
, а затем решил использовать $.map()
в качестве рекомендуемого Томислава Марковского в аналогичном вопросе
У кого-нибудь есть идея, почему я продолжаю получать эту проблему?!
Спасибо
Ответы
Ответ 1
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;
}
});
Ответ 2
В моем случае я получил эту точную ошибку, и оказалось, что версия Bootstrap, которую я использовал (2.0.4), не поддерживала передачу функции в настройку source
.
Обновление до Bootstrap 2.1.1 устраняет проблему.
Ответ 3
ОБНОВЛЕНО/ПЕРЕСМОТРЕННЫЙ ВЗГЛЯД НА НОМЕР: Ошибка, о которой вы упомянули, "Не удалось вызвать метод" toLowerCase "из undefined" возникла у меня, когда я использовал оригинальное расширение Typeahead в бутстрапе, которое не поддерживает AJAX. (как вы уже нашли) Вы уверены, что исходное расширение typeahead не загружается, а не пересмотрено?
Я был успешно используя этот Gist of typehead, который является небольшим изменением по сравнению с тем, которое вы упомянули. Как только я переключился на этот Gist и подтвердил, что входные данные были хорошими (проверка того, что вход был строковым массивом в объекте JS, проблема исчезла.
Надеюсь, что это поможет
Оригинальный ответ:
Причина, по которой происходит ошибка, заключается в том, что значение, переданное в функцию matte-type, называется undefined. Это всего лишь побочный эффект реальной проблемы, которая возникает где-то между вашим входом и этой функцией сопряжения. Я подозреваю, что массив "производителей" имеет проблему. Сначала проверьте его, чтобы убедиться, что у вас есть допустимый массив.
// It appears your array constructor is missing ()
// try the following in your binding code:
var manufacturers = new Array();
Вот что я использую для привязки ввода к typeahead. Я подтвердил, что он работает с вашей модифицированной вилкой типа head.
Мой 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);
});
}
});
Ответ 4
В моем случае у меня были нулевые значения в моем исходном массиве, вызвавшие эту ошибку.
Упрощенный пример:
source : ["item 1", "item 2", null, "item 4"]
Ответ 5
Объекты вашего производителя не имеют свойства "name", вы должны изменить
property: 'name',
к
property: 'manufacturer',
Ответ 6
Пробовали ли вы использовать переменные сопоставления, например, пример ниже, вам нужно использовать это, когда у вас есть больше одного свойства в вашем объекте;
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);
}
Ответ 7
Я наткнулся на этот вопрос некоторое время назад. Я советую вам перепроверить конфигурацию, в которой вы включаете библиотеки typeahead
(через main.js, app.js или config.js).
В противном случае вы можете перезаписать последнюю версию Bootstrap в свою библиотеку приложений.
Ответ 8
Попробуйте этот код:
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]);
}
});
Ответ 9
Я решил эту проблему только обновить файл bootstrap3-typeahead.min.js к файлу в https://github.com/bassjobsen/Bootstrap-3-Typeahead/blob/master/bootstrap3-typeahead.min.js
Я думаю, что большинство людей могут решить этот путь.