2013-07-10 2 views
8

Хорошо, я боролся с этой проблемой в течение нескольких часов в настоящее время и сузили вопрос очень простой FiddleTwitter Bootstrap выбор машинописный не связан KnockoutJS

Проблема в том, что, когда я использую машинописный Twitter Bootstrap в плагин на текстовый ввод и сделать выбор, это значение не обновляется в ViewModel KnockoutJS. Я знаю, что я мог бы взломать его на работу, но должно быть что-то, что мне здесь не хватает.

В основном то, что у меня есть:

Нокаут Связывание

// Bind twitter typeahead 
ko.bindingHandlers.typeahead = { 
    init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { 
     var $element = $(element); 
     var allBindings = allBindingsAccessor(); 
     var typeaheadArr = ko.utils.unwrapObservable(valueAccessor()); 

     $element.attr("autocomplete", "off") 
       .typeahead({ 
        'source': typeaheadArr, 
        'minLength': allBindings.minLength, 
        'items': allBindings.items, 
        'updater': allBindings.updater 
       }); 
    } 
}; 

Нокаут ViewModel

function MyModel(){ 
    var self = this; 
    self.productName = ko.observable(); 
    self.availableProducts = ['One', 'Two', 'Three']; 
} 

ko.applyBindings(new MyModel()); 

HTML

<input type="text" data-bind="typeahead:availableProducts, value:productName"/> 

Остальная часть материала просто происходит из Twitter Bootstrap.

+1

Я не являюсь автором переплета. Оригинальное связывание здесь: https://github.com/billpull/knockout-bootstrap. Интересно, пропустил ли я что-то в использовании ??? –

ответ

4

Одним из решений являются модифицировать updater функции, где вы должны захватить наблюдаемые, используемые в value связывания и обновлять его с функцией параметром Я:

'updater': function(item) { 
    allBindings.value(item); 
    return item; 
} 

Демо JSFiddle.

Если вы не являетесь автор обязательного использования вами, вы можете использовать опцию updater для указания функции updater

data-bind="typeahead:availableProducts, 
      updater: function(item) { productName(item); return item; }" 

Поскольку updater должен возвращать выбранный элемент, синтаксис этого не очень приятный.

Demo JSFiddle.

+0

Хорошо, это работает нормально. Можете ли вы объяснить, почему это работает против предыдущей реализации? Я не автор нокаута. Я хотел бы понять, что думал автор, когда он ввел allBindings.updater в программу обновления, и если есть «правильный» способ использования привязки. Что-то, чего мне не хватает в HTML, может быть? Оригинальный плагин находится здесь: https://github.com/billpull/knockout-bootstrap –

+0

Я не знал, что это привязка находится в библиотеке. Я изменил свой ответ на работу с исходным кодом. Что касается того, почему автор разработал API таким образом, я понятия не имею. Мне не удалось найти какой-либо пример в github, который использует параметр «updater». Поэтому я бы сказал, что это «ошибка API-дизайна» в библиотеке, потому что мы говорим о библиотеке ko-bootstrap, которая должна быть более идиоматически использована KO. Так можно представить себе что-то подобное в качестве правильной реализации: http://jsfiddle.net/wTRhF/ – nemesv

+0

Я думаю, что оригинальная реализация хорошо работает с функциями, а не просто связыванием значений. В основном функция updater делает то, что она должна делать с выбранным значением, здесь ее назначить наблюдаемому ko. Решение nemesv является кратким из этого. –

3

Этот материал обновления не работает для меня, вот что сделал

ko.bindingHandlers.typeahead = { 
    init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { 
     var $element = $(element); 
     var allBindings = allBindingsAccessor(); 
     var typeaheadArr = ko.utils.unwrapObservable(valueAccessor()); 

     var updateValues = function (val) { 
      allBindings.value(val); 
     }; 

     $element.attr("autocomplete", "off") 
       .typeahead({ 
        'local': typeaheadArr, 
        'minLength': allBindings.minLength, 
        'items': allBindings.items, 
       }).on('typeahead:selected', function (el, item) { 
        updateValues(item.value); 
       }).on('typeahead:autocompleted', function (el, item) { 
        updateValues(item.value); 
       }); 
    } 
}; 
3

Я предпочитаю, чтобы мой список предложений автозаполнения отдельно от выбивания полностью. Я хочу, чтобы Knockout узнал, как только пользователь действительно ввел значение.

Это ближе к технике пользователя2576666, так как оно использует Typeahead's custom events для принудительного обновления в модели нокаута, когда есть выбор или автозаполнение. Тем не менее, он не требует специального привязки typeahead и не требует, чтобы значения сохранялись в модуле нокаута ViewModel. Это открывает возможности для более настраиваемого завершения работы по линии (например, с помощью Bloodhound), который будет бесполезно запутан, если мы попытаемся сохранить его в модели Knockout. Мой ViewModel определенно не подходит для хранения параметров автозаполнения для моего варианта использования (и, я бы предложил, многие другие, особенно если у вас есть потенциально большой список, который требует динамической совокупности).ИМО эта версия также проще понять:

var availableProducts = ['One', 'Two', 'Three']; 

var substringMatcher = function(strs) { 
    return function findMatches(q, cb) { 
    var matches, substrRegex; 
    matches = []; 
    substrRegex = new RegExp(q, 'i'); 
    $.each(strs, function(i, str) { 
     if (substrRegex.test(str)) { 
     matches.push({ value: str }); 
     } 
    }); 
    cb(matches); 
    }; 
}; 


function MyModel(){ 
    var self = this; 
    self.productName = ko.observable(); 
} 

var myModel = new MyModel(); 

ko.applyBindings(myModel); 

var onUpdated = function($e, datum) { 
    myModel.productName(datum.value); 
}; 

$(".typeahead") 
    .typeahead(
     {hint: true, minLength: 1, highlight: true}, 
     {displayKey: 'value', source: substringMatcher(availableProducts)}) 
    .on('typeahead:autocompleted', onUpdated) 
    .on('typeahead:selected', onUpdated); // for knockoutJS 

Я, конечно, сохранить это как a JSFiddle:

Смежные вопросы