2013-07-10 99 views
8

好了Twitter的引導預輸入選擇,我這個問題,現在爭取小時,縮小了問題很簡單Fiddle不受KnockoutJS約束

問題是,當我使用Twitter的引導的預輸入插件上一個文本輸入並進行選擇,該值不會在KnockoutJS ViewModel中更新。我知道我可以破解它的工作,但必須有一些我在這裏失蹤的東西。

基本上我有是:

淘汰賽綁定

// 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 
       }); 
    } 
}; 

淘汰賽視圖模型

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

一種解決方案是,你需要搶在value可觀察使用綁定,並使用該函數放慢參數更新它來修改你updater功能:

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

演示JSFiddle.

如果不是綁定的作者比你可以使用updater選項指定updater函數

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

因爲updater應該返回所選項目,所以它的語法不太好。

演示JSFiddle.

+0

好的,這似乎工作正常。你能解釋爲什麼這與以前的實施相比有效嗎?我不是淘汰賽的作者。我想了解原作者在將所有Binding.updater放入更新程序時的想法,以及是否存在使用綁定的「正確」方式。我在HTML中缺少的東西可能是什麼?原來的插件是在這裏:https://github.com/billpull/knockout-bootstrap –

+0

我不知道這個綁定是在一個庫中。我修改了我的答案以使用原始代碼。關於作者爲何以這種方式設計API,我不知道。我無法在使用'updater'選項的github上找到任何示例。所以我會說這是庫中的「API設計錯誤」,因爲我們正在討論ko-bootstrap庫,它應該更習慣於使用KO。所以可以想象這樣的正確實現:http://jsfiddle.net/wTRhF/ – nemesv

+0

我認爲最初的實現可以很好地用函數而不是簡單的值綁定。基本上,updater函數完成它需要處理的選定值,在這裏它被分配給ko observable。 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在存在選擇或自動完成時強制更新Knockout模型。但是,它不需要預先定製綁定,也不需要將值存儲在Knockout ViewModel中。這爲開展更多可定製完成的範圍打開了空間(例如使用Bloodhound),如果我們試圖將其存儲在Knockout模型中,這將不必要地繁瑣。我的ViewModel絕對不是存儲我的用例的自動完成選項的正確位置(並且,我建議,還有其他很多 - 特別是如果您有可能需要動態人口的大型列表)。IMO這個版本也更容易理解:

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