Skip to content Skip to sidebar Skip to footer

Selected Option Is Not Updated When Observable Updates, Though OptionsValue Does

In the following code, a product (represented with productVM) has an observable property (productName) containing its name in two languages (english and french). Once a cartItem is

Solution 1:

Your problem occurs when you change the options of your select. During the change, your value bound observable, cartItemName, contains the English string. For example: Door. As soon as you change the language, there is not a single option that returns Door for its optionsValue expression, thereby clearing the value altogether.

The best solution is to store a reference to your actual viewmodel, rather than just its string name. This does require you to move some other bits & pieces around, since you're manually updating quite a bit.

The starting point of the change:

// Remove
self.cartItemName = ko.observable(); 

// Add
self.cartItem = ko.observable();

// Change
<select data-bind="...
  value: cartItem
" />

In a working snippet, with some other changes to make my work easier:

var handlerVM = function () {
  var self = this;

  self.cartItems = ko.observableArray([]);
  self.language = ko.observable("english");
  self.availableProducts = ko.observableArray([
    new productVM("Shelf", ['White', 'Brown']),
    new productVM("Door", ['Green', 'Blue', 'Pink']),
    new productVM("Window", ['Red', 'Orange'])
  ]);

  self.productNameFor = function(product) {
    return product.productName()[self.language()];
  };
  
  self.addCartItem = function (a, b, c, d) {
    self.cartItems.push(new cartItemVM());
  }
  
  self.changeLanguage = function () {
    self.language() == "english" ?
      self.language("french") :
      self.language("english");
  }
}
self.productVM = function (name, availableColours) {
  var self = this;
  self.productName = ko.observable({
    english: name,
    french: name + "eux",
  });
  self.availableColours = ko.observableArray(availableColours);
}

self.cartItemVM = function () {
  var self = this;
  self.cartItem = ko.observable();
  self.cartItemColour = ko.observable();
}

ko.applyBindings(new handlerVM());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<div>
  <div data-bind="foreach: cartItems">
    <div>
      <select data-bind="options: $root.availableProducts,
                optionsText: $root.productNameFor,
                optionsCaption: 'Choose a product',
                value: cartItem"
      >
      </select>
    </div>
    <div data-bind="with: cartItem">
      <select data-bind="options: availableColours,
                optionsCaption: 'Choose a colour',
                value: $parent.cartItemColour"
      >
      </select>
    </div>
  </div>
  <div>
    <button data-bind="text: 'add cart item', click: addCartItem" />
    <button data-bind="text: 'change language', click: changeLanguage" />
  </div>
</div>

Post a Comment for "Selected Option Is Not Updated When Observable Updates, Though OptionsValue Does"