1
votes

Using Knockout JS, when a user types into an input field and selects a value (ex: Fruit) using jquery-ui autocomplete selection, I'm trying to change the select drop-down of options in a separate drop-down.

Example scenario: (1) User begins to type "Fru.." (2) Selects "Fruit" in autocomplete input field. (3) Dropdown options changes based on the value: "Fruit" (4) Dropdown options only shows "Apples" or other options with equals id (ex: ABC)

Autocomplete Input Field

HTML

<input type="text"
    id="searchItem"
    placeholder="Search"
    tabindex="0"
    data-bind="textInput: searchItem, valueUpdate: 'onkeyup'"/>

ViewModel/JQuery (Autocomplete)

// Search Item
$(function() {
    var searchItem = [
        { id: "ABC", name: "Fruit" },
        { id: "DEF", name: "Animal" },
        { id: "GHI", name: "Color" },
        { id: "JKL", name: "Clothing" }
    ];

    $("#searchItem").autocomplete({
      source: searchItem
    });

 });

Select dropdown

HTML

<select class="form-control"
        id="alphabetList"
        data-toggle="tooltip"
        tabindex="0"
        data-bind=" foreach: { data: alphabetList, as: 'item' }, value: selectedItem">
    <option data-bind=" attr: { 'value': item.id }, text: item.name"></option>
</select>

ViewModel

// Alphabet List
this.alphabetList = ko.observableArray([
    { id: "ABC", name: "Apples" },
    { id: "DEF", name: "Dog" },
    { id: "GHI", name: "Green" },
    { id: "JKL", name: "Jacket" }
]);
1

1 Answers

1
votes

On selection of an item in autocomplete, populate an observable called selectedId. Then create a computed property which filters the alphabetList based on selectedId

You have not mentioned where this autocomplete code exists. But, since you have mentioned ViewModel, I'm assuming you have access to the viewModel's instance in your jquery code.

Also, you don't need to use the foreach binding for displaying options. You can use options binding.

Here's a working snippet with all these changes:

var viewModel = function() {
  var self = this;
  self.selectedAlphabet = ko.observable();
  self.selectedId = ko.observable();
  self.searchItem = ko.observable();
  
  self.alphabetList = ko.observableArray([
      { id: "ABC", name: "Apples" },
      { id: "DEF", name: "Dog" },
      { id: "GHI", name: "Green" },
      { id: "JKL", name: "Jacket" }
   ]);

  // this gets triggerred everytime selectedId changes 
  self.availableAlphabetList = ko.pureComputed(() => {
    return self.alphabetList().filter(item => item.id == self.selectedId());
  });
}

// I have created an instance to use it in jquery code
var instance = new viewModel();

ko.applyBindings(instance);

$(function() {
   var searchItem = [
   { id: "ABC", name: "Fruit" },
   { id: "DEF", name: "Animal" },
   { id: "GHI", name: "Color" },
   { id: "JKL", name: "Clothing" }];

  $("#searchItem").autocomplete({
    // creating an array with a "label" property for autocomplete
    source: searchItem.map(function(item) {
      return {
        label: item.name,
        id: item.id
      }
    }),
    // on select populate the selectedId
    select: function(event, ui) {
      // if this jquery code is within viewModel, then use "self.selectedId"
      instance.selectedId(ui.item.id)
    }
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.9.2/jquery-ui.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.9.2/themes/base/jquery-ui.css">

<input type="text" id="searchItem" placeholder="Search" tabindex="0" data-bind="textInput: searchItem, valueUpdate: 'onkeyup'" />

<select class="form-control" id="alphabetList" data-toggle="tooltip" tabindex="0" data-bind="options: availableAlphabetList, 
                      optionsText: 'name',
                      optionsValue: 'id',
                      value: selectedAlphabet
                      optionsCaption: 'Choose..'">
</select>

You can also go through this question which has good answers for creating a custom binding for autocomplete