【问题标题】:selected option is not updated when observable updates, though optionsValue does当可观察更新时,选择的选项不会更新,尽管 optionsValue 确实
【发布时间】:2018-11-02 10:55:20
【问题描述】:

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

添加cartItem 并选择产品后,我希望在单击“更改语言”按钮时更新其显示名称(例如,如果选择了“门”,并且“更改语言”为然后点击,显示的名称应该是法语版本(它只是英文单词加上法语后缀“eux”))。

但这不起作用:选项确实发生了变化,但所选选项更改为标题选项。

需要更改/添加什么来修复它?

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>

【问题讨论】:

    标签: javascript knockout.js options


    【解决方案1】:

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

    最好的解决方案是存储对实际视图模型的引用,而不仅仅是其字符串名称。这确实需要您移动其他一些零碎的东西,因为您要手动更新很多东西。

    变化的起点:

    // Remove
    self.cartItemName = ko.observable(); 
    
    // Add
    self.cartItem = ko.observable();
    
    // Change
    <select data-bind="...
      value: cartItem
    " />
    

    在一个正常工作的 sn-p 中,进行了一些其他更改以使我的工作更轻松:

    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>

    【讨论】:

    • 介意看看我的其他相关question?
    • @HeyJude 当然,我今天晚些时候再看看!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-07-09
    • 1970-01-01
    • 2018-03-17
    • 2021-10-26
    • 2019-02-10
    • 2013-12-16
    • 2012-11-26
    相关资源
    最近更新 更多