0

After I finally was able to add and remove items from a list (see fiddle), I moved on to implement jQuery Autocomplete.

After looking at Rune's example and Rene's example, I am able to trigger Autocomplete. But when I select an item, the values are not added to my hidden input and my search box.

My current solution follows Rune's example, but I might simplyfy it and follow Rene's example once I'm able to bind the selected item.

So my question is: How can I bind the selected items? I've created a Fiddle to test.

PS. I'm having issues in the Fiddle when putting search data in array (instead of getting from DB). But that is not my main problem.

Here is the part of the code regarding Autocomplete:

My HTML:

<input type="hidden" value="" data-bind="value: item_id" />
<input class="form-control" type="search" data-bind="value: item_name, autoComplete: items" />     
...
<ul class="list-group" data-bind="template: { name: 'item-template', data: $root.items}">
...
</ul>

My JS;

// Retrieved from DB
var search_data = [
    {"id":"7186","name":"Bose"},
    {"id":"1069","name":"BOSS Black"},
    {"id":"1070","name":"BOSS Green"},
    {"id":"1071","name":"BOSS Hugo Boss"},
    {"id":"1072","name":"BOSS Orange"},
    {"id":"1074","name":"Boston Brothers"},
    {"id":"7678","name":"Bosweel"}
];

ko.bindingHandlers.autoComplete = {
    init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var selectedObservableArrayInViewModel = valueAccessor();
        var self = bindingContext;
        self.item_id = ko.observable();
        self.item_name = ko.observable();    

        $(element).autocomplete({
            minLength: 2,
            source: function (request, response) {
                $.ajax({
                    source: search_data,
                    data: { term: request.term },
                    type: "POST",
                    dataType: "json",
                    success: function (data) {
                        response(data);
                    }
                });
            },
            select: function(e, ui){
                var item = ui.item;
                self.item_name = ko.observable(item.name);
                self.item_id = ko.observable(item.id);
            }
        }).data( "uiAutocomplete" )._renderItem = function( ul, item ) {
            return jQuery( "<li></li>" )
            .data( "ui-autocomplete", item )
            .append( "<a>"+ item.name + "</a>" )
            .appendTo( ul );
        }

    }
};
Community
  • 1
  • 1
Steven
  • 19,224
  • 47
  • 152
  • 257

1 Answers1

1

I am not sure I understand your question, so I am not sure this answers it.

First, you need to replace this

var self = bindingContext;

With this

var self = viewModel;

Then, in your select function, don't re-create your observables, update them and then call your addItem function:

select: function(e, ui){
            var item = ui.item;
            self.item_name(item.name);
            self.item_id(item.id);
            self.addItem();
        }

Updated fiddle (I removed your ajax call to show all items without filtering, just for the demo -- ajax call was failing)

EDIT:

In the previous fiddle, the input is cleared after the selection of an item.

Add return false; to the end of the select function to avoid that.

New fiddle

GôTô
  • 7,974
  • 3
  • 32
  • 43
  • That works great, thanks! Just one thing. If I remove `self.addItem()`, why isn't my selection showing in the search box? – Steven May 17 '14 at 15:08
  • @Steven What do you call the search box? Is it the list of found items? The found items are filled with the call to the `response` function. The `select` function is called when you click on one of the found items, this is the place where you need to add the item to the `items` observableArray. – GôTô May 17 '14 at 15:13
  • Exactly. So when I click it, I want to see the name in the search box. The searchbox is the ` – Steven May 17 '14 at 15:18
  • @Steven answer updated. It's often a `return false` to avoid further action – GôTô May 17 '14 at 15:34