jQuery UI autocomplete with a Knockout binding handler

Using the jQuery UI AutoComplete widget with Knockout js


<button data-bind="click: updateDataSource">Update Data Source</button>
<label for="name-search">Search language:</label>
<input type="text" id="name-search" data-bind="value: langName, 
ko_autocomplete: { minLength : 0, source: languages, select: addLang }" />
<div style="margin-top:1em">The observable array contains the following elements:
    <ul data-bind="foreach: selectedLangs">
        <li data-bind="text: $data" />
    </ul>
</div>
ko.bindingHandlers.ko_autocomplete = {
    init: function (element, params) {
        //We make a shallow copy of the object because we will change it
        var conf = $.extend({}, params());

        // This fixes the problem of showing the value instead of the label when pressing up or down
        if (!conf.focus) {
            //There is no focus callback defined so we will add one
            conf.focus = function (event, ui) {
                $(element).val(ui.item.label);
                return false;
            }
        }

        // Use this to check if the autocomplete is already initialize
        var isAutoComplete = $(element).is(':data(autocomplete)');

        // Use an observable instead of a fixed array
        var source = conf.source; // <- assuming an observable here                            
        conf.source = source(); // get the actual content        
        $(element).autocomplete(conf);      
                
        if (!isAutoComplete) {
            //watch for modifications
            var subscription = source.subscribe(function (newValue) {
                $(element).autocomplete("option", "source", newValue);
            });                                                
            
            //handle disposal                                    
            ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
                subscription.dispose();
                $(element).autocomplete("destroy");
            });
        }
    },
    update: function (element, params) {
        $(element).autocomplete("option", "source", params.source);
        return false;
    }
}

$(function () {

    var availableTags = [{
        label: "ActionScript",
        value: 1
    }, {
        label: "AppleScript",
        value: 2
    }, {
        label: "Asp",
        value: 3
    }, {
        label: "BASIC",
        value: 4
    }, {
        label: "C",
        value: 5
    }, {
        label: "C++",
        value: 6
    }, {
        label: "Clojure",
        value: 7
    }, {
        label: "COBOL",
        value: 8
    }, {
        label: "ColdFusion",
        value: 9
    }, {
        label: "Erlang",
        value: 10
    }, {
        label: "Fortran",
        value: 11
    }, {
        label: "Groovy",
        value: 12
    }, {
        label: "Haskell",
        value: 13
    }, {
        label: "Java",
        value: 14
    }, {
        label: "JavaScript",
        value: 15
    }, {
        label: "Lisp",
        value: 16
    }, {
        label: "Perl",
        value: 17
    }, {
        label: "PHP",
        value: 18
    }, {
        label: "Python",
        value: 19
    }, {
        label: "Ruby",
        value: 20
    }, {
        label: "Scala",
        value: 21
    }, {
        label: "Scheme",
        value: 22
    }];

    // knockout view model                    
    var ViewModel = function () {

        var self = this;

        self.langName = ko.observable();
        self.selectedLangs = ko.observableArray();

        self.languages = ko.observableArray(availableTags);

        self.updateDataSource = function () {
            self.languages.push({
                label: 'Brain F...',
                value: 25
            });
        }

        // user clicked on a auto complete item
        self.addLang = function (event, ui) {

            $(event.target).val("");

            var lang = ui.item.label;
            var id = ui.item.value;

            self.selectedLangs.push("id: " + id + ", Language: " + lang);

            return false;
        }

        return {
            languages: self.languages,
            updateDataSource: self.updateDataSource,
            addLang: self.addLang,
            langName: self.langName,
            selectedLangs: self.selectedLangs
        }
    };

    //bind knockout model
    ko.applyBindings(new ViewModel());

});
DEMO
jQuery UI autocomplete with a Knockout binding handler jQuery UI autocomplete with a Knockout binding handler Reviewed by Bhaumik Patel on 8:39 PM Rating: 5