可观察到的更新时,所选选项不会更新,尽管optionsValue确实会更新 [英] selected option is not updated when observable updates, though optionsValue does

查看:69
本文介绍了可观察到的更新时,所选选项不会更新,尽管optionsValue确实会更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在下面的代码中,产品(用productVM表示)具有可观察的属性(productName),其中包含以两种语言(英语和法语)表示的名称.

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

一旦添加了cartItem并选择了产品,我希望在单击更改语言"按钮时更新其显示名称(例如,如果选择了门",而更改语言"是然后单击,显示的名称应为法语版本(这是英文单词加上法文后缀"eux").

Once a cartItem is added, and a product is selected, I want its displayed name to be updated when the button "change language" is clicked (e.g., if "Door" is selected, and "change language" is then clicked, the displayed name should be the french version (which is simply the english word plus a french-ish suffix "eux")).

但是它不起作用:选项会更改,但是所选的选项会更改为标题选项.

But it doesn't work: The options do change, but the selected option is changed to the caption option.

需要更改/添加哪些内容来解决它?

What needs to be changed/added to fix it?

var handlerVM = function () {
  var self = this;
  self.cartItems = ko.observableArray([]);
  self.availableProducts = ko.observableArray([]);
  self.language = ko.observable();
  self.init = function () {
    self.initProducts();
    self.language("english");
  }
  self.initProducts = function () {
    self.availableProducts.push(
      new productVM("Shelf", ['White', 'Brown']),
      new productVM("Door", ['Green', 'Blue', 'Pink']),
      new productVM("Window", ['Red', 'Orange'])
    );
  }
  self.getProducts = function () {
    return self.availableProducts;
  }
  self.getProductName = function (product) {
    if (product != undefined) {
      return self.language() == "english" ? 
        product.productName().english : product.productName().french;
    }
  }
  self.getProductColours = function (selectedProductName) {
    selectedProductName = selectedProductName();
    // if not caption
    if (selectedProductName) {
      var matched = ko.utils.arrayFirst(self.availableProducts(), function (product) {
        return (self.language() == "english" ? product.productName().english : product.productName().french) == selectedProductName;
      });
      return matched.availableColours;
    }
  }
  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.cartItemName = ko.observable();
  self.cartItemColour = ko.observable();
}

var handler = new handlerVM();
handler.init();
ko.applyBindings(handler);

<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: $parent.getProducts(),
                optionsText: function (item) { return $parent.getProductName(item); },
                optionsValue: function (item) { return $parent.getProductName(item); },
                optionsCaption: 'Choose a product',
                value: cartItemName"
      >
      </select>
    </div>
    <div>
      <select data-bind="options: $parent.getProductColours(cartItemName),
                optionsText: $data,
                optionsCaption: 'Choose a colour',
                value: cartItemColour,
                visible: cartItemName() != undefined"
      >
      </select>
    </div>
  </div>
  <div>
    <button data-bind="text: 'add cart item', click: addCartItem" />
    <button data-bind="text: 'change language', click: changeLanguage" />
  </div>
</div>

推荐答案

当您更改所选内容的options时,就会出现您的问题.在更改期间,value绑定的可观察值cartItemName包含 English 字符串.例如:Door.更改语言后,没有一个option为其optionsValue表达式返回Door,从而完全清除了value.

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.

更改的起点:

// 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>

这篇关于可观察到的更新时,所选选项不会更新,尽管optionsValue确实会更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆