Knockout.js binding for Bootstrap Typeahead plugin


Here’s a rather hacky script I wrote to bind fields marked up with Bootstrap’s Typeahead plugin (see https://gist.github.com/1866577 for the version I use) to Knockout.js observables. Feedback is very welcome.

// Bootstrap.Typeahead binding: presently requires custom version from gist: https://gist.github.com/1866577.
// Use like so: data-bind="typeahead: { target: selectedNamespace, source: namespaces }"
ko.bindingHandlers.typeahead = {
  init: function(element, valueAccessor) {
    var binding = this;
    var elem = $(element);
    var value = valueAccessor();

    // Setup Bootstrap Typeahead for this element.
    elem.typeahead(
    {
      source: function() { return ko.utils.unwrapObservable(value.source); },
      onselect: function(val) { value.target(val); }
    });

    // Set the value of the target when the field is blurred.
    elem.blur(function() { value.target(elem.val()); });
  },
  update: function(element, valueAccessor) {
    var elem = $(element);
    var value = valueAccessor();
    elem.val(value.target());
  }
};

Update: Binding now uses only the valueAccessor, rather than looking for a separate ‘source’ binding. This is cleaner.

Comments (13)

  1. hello says:

    did u ever test this out?

  2. Reuben.Bond says:

    Of course 🙂 Note the comment regarding the need to use the gist version. You can achieve the same thing using Bootstrap 2.2.0, patching it as per this GitHub comment: github.com/…/5063

  3. Do you have an example on fiddle? says:

    It helps me understand it easier. Or do you got google talk?

  4. I don't want to dabble with the library says:

    I don't want to dabble with the library, i am getting a json array back and want to bind it. What would be the binding on the html tag?

  5. Reuben.Bond says:

    Something like this:

     <span>Namespace</span><input type="text" data-bind="typeahead: { target: selectedNamespace, source: namespaces }">

    In that example, selectedNamespace is the observable which is being set by the input and namespaces is the observable which contains the data. In your example, you might set the source using something like:

    self.namespaces = ko.observable();

    $.getJSON('/namespaces', self.namespaces);

  6. Hmmm says:

    So namespaces has the array, while selectedNamespace refers to the textbox value?

  7. Looking at the function is says:

    is valueAccessor is array of values and

    element is teh id of the textbox?

  8. Reuben.Bond says:

    > So namespaces has the array, while selectedNamespace refers to the textbox value?

    yes

    >is valueAccessor is array of values and

    >element is teh id of the textbox?

    No, checkout the Knockout.js docs: knockoutjs.com/…/custom-bindings.html

    They should answer your questions succinctly.

  9. It doesn't seem to work says:

    I added an array straight

    this.List = ['alpha', 'anna', 'atakata','baba', 'bella'];

    this.typeahead = ko.observable();

    and i referenced them. using the binding:

    <input id="typeahead" type="text" data-bind="typeahead: { target: typeaheadbox, source: customerList }", valueUpdate: 'afterkeydown'" >

  10. Reuben.Bond says:

    Well in my usage, I'm using an observable, not a native array(shouldn't matter). Also, your code there is not syntactically valid HTML or XML – what's that superfluous:

      , valueUpdate: 'afterkeydown'"

    bit for?

  11. , valueUpdate: 'afterkeydown'" says:

    This basically updates the box after each key press rather than when there is a loss of focus.

  12. Array updates dynamically says:

    my array updates each time the key is pressed via a json call, it doesn't always have all the elements.

  13. Reuben.Bond says:

    If you really want, I will try and fix your code for you… but I think you should run through the Knockout.js tutorials and the Bootstrap documentation first, then ask on StackOverflow.

    Also, consider putting your own code on JSFiddle so I can see it.

Skip to main content