Search code examples
twitter-bootstrapknockout.jsbootstrap-typeahead

Twitter Bootstrap typeahead selection not bound by KnockoutJS


Ok, I've fought with this issue for hours now and narrowed the issue to a very simple Fiddle

Problem is, that when I'm using twitter bootstrap's typeahead plugin on a text input and make a selection, the value doesn't update in the KnockoutJS ViewModel. I know I could hack it to work but there must be something that I'm missing here.

Basically what I have is:

Knockout Binding

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

Knockout 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"/>

The rest of the stuff is simply coming from Twitter Bootstrap.


Solution

  • One solution is to modify your updater function where you need to grab the observable used in the value binding and update it with the function paramter:

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

    Demo JSFiddle.

    If you are not the author of the binding you than you can use the updater option to specify the updater function

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

    Because the updater should returns the selected item the syntax of this is not so nice.

    Demo JSFiddle.