Typeahead.js not working in Knockout 3 foreach binding
Asked Answered
B

2

4

I updated a web app to Bootstrap 3 and Knockout 3 and consequently lost the built in typeahead that was in Bootstrap 2. I added typeahead.js and it works great unless I have a typeahead within a Knockout 'foreach' binding. I included code that works and fails below along with the Javascript code for the typeahead and Bootstrap binding. Any ideas?

<form role="form">
    <div class="row">
        <div class="col-sm-4 form-group">
            <input type="text" class="form-control sectionNames" data-bind="value: name" />
        </div>
    </div>
    <div data-bind="foreach: section">
        <div class="row">
            <div class="col-sm-4 form-group">
                <input type="text" class="form-control sectionNames" data-bind="value: name" />
            </div>
        </div>
    </div>
</form>

Javascript for typeahead.js and Knockout bindings

<script>
    $( document ).ready(function() {
        $('input.sections').typeahead({
            name: 'sectionName',
            local: [
                'ABC',
                'DEF'
            ]
        });

        ko.applyBindings({
            section : [
                { name: "", other: "1234" },
                { name: "", other: "5678" }
            ]
        });
    });
</script>
Basswood answered 9/12, 2013 at 20:7 Comment(0)
A
7

Your best bet for something like a widget, especially when you are rendering elements via templating/control-flow, is to use a custom binding to initialize the widget. For example, you could use something like this:

ko.bindingHandlers.typeahead = {
    init: function(element, valueAccessor) {
        var options = ko.unwrap(valueAccessor()) || {},
            $el = $(element),
            triggerChange = function() {
                $el.change();   
            }

        //initialize widget and ensure that change event is triggered when updated
        $el.typeahead(options)
            .on("typeahead:selected", triggerChange)
            .on("typeahead:autocompleted", triggerChange);        

        //if KO removes the element via templating, then destroy the typeahead
        ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
            $el.typeahead("destroy"); 
            $el = null;
        }); 
    }
};

Here is a sample: http://jsfiddle.net/rniemeyer/uuvUR/

Adventurer answered 10/12, 2013 at 19:8 Comment(3)
Thank you Ryan. While this is more complex than I hoped, I always appreciate your informative and demonstrable responses. Really appreciate you taking the time to create the jsfiddle! I'm going to see if I can get this to work in my app now.Basswood
Ryan for some reason Typeahead.js is no longer available in that fiddle from CDN - I fixed the reference to be from cdnjs - jsfiddle.net/uuvUR/12 - Could you update for future users and I will remove this comment?Bertina
@RPNiemeyer -Sir will you see this once #25499221Michaella
A
2

You should just override events which respond for valueUpdate in KO

<input type="text"
       class="form-control sectionNames"
       data-bind="
           value: name, 
           valueUpdate: 'typeahead:selected typeahead:autocompleted"
/>
Authorship answered 16/7, 2014 at 11:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.