如何处理绑定:更改 observableArray 中的数据后的 foreach

Posted

技术标签:

【中文标题】如何处理绑定:更改 observableArray 中的数据后的 foreach【英文标题】:How to process binding : foreach after altering data in observableArray 【发布时间】:2020-11-02 20:56:37 【问题描述】:

我正在更改 observableArray,修改订阅事件中的一些数据。首先,我使用 ko.toJS() 转换 ObservableArray,通过数据映射并进行更改。最后我调用 self.menuCategories(jsArray) 再次设置 observableArray。

似乎我以某种方式失去了与 observableArray 的“连接”,因为我的代码中的 foreach 语句突然中断。

要么有一种更简单的方法来处理这个问题,要么我没有正确处理 observables。

代码:

var MenuWizardModel = function() 
   var self = this;
   self.menuCategories = ko.observableArray();
   self.commonDiscount = ko.observable(0);

   // Handling adding items to menuCategories.
   self.addNewSubMenuItem = function () 
        var newSubMenuItem = new SubMenuItemViewModel(self.newSubMenuItemName(), []);
        self.menuCategories.push(newSubMenuItem);
        self.newSubMenuItemName(null);
        self.createNewSubMenu(false);
    

  function SubMenuItemViewModel(name, foodItemList) 
       var self = this;
       self.name = ko.observable(name);
       self.foodItemList = ko.observableArray(foodItemList);
  

   self.commonDiscount.subscribe(function(val) 
        var discount = parseInt(val) / 100;
        var jsArray = ko.toJS(self.menuCategories);
        console.log(jsArray)
        jsArray = ko.toJS(jsonArray[0].foodItemList.map(item => 
            item.price = parseInt(item.price) - (parseInt(item.price) * discount);
            return item;
        ));
        self.menuCategories(jsArray);
    );

标记:

 <div data-bind="foreach: menuCategories">
          <h4 data-bind="text: name"></h4>
          <div data-bind="foreach: foodItemList" class="list-group">
          ...

数据:

【问题讨论】:

【参考方案1】:

我认为处理这类事情的最佳方法是向 fooditem 添加一个计算出的 observable 来捕获全局折扣并计算折扣价。

类似于以下内容。

var MenuWizardModel = function() 
  var self = this;
  self.menuCategories = ko.observableArray([
    name: 'Main Meals'
  ]);
  self.commonDiscount = ko.observable(0);
  self.newSubMenuItemName = ko.observable();
  
  // Handling adding items to menuCategories.
  self.addNewSubMenuItem = function() 
    var newSubMenuItem = new SubMenuItemViewModel(self.newSubMenuItemName(), [name: 'Oranges', price: 3.99]);
    self.menuCategories.push(newSubMenuItem);
    self.newSubMenuItemName(null);
    //self.createNewSubMenu(false);
  
  function mapFoodItem(item)
    item.discountedPrice= ko.pureComputed(function()
      var discount = parseInt(self.commonDiscount()) / 100
      return parseInt(item.price) - (parseInt(item.price) * discount);
    );
    return item;
  
  
  function SubMenuItemViewModel(name, foodItemList) 
    var self = this;
    self.name = ko.observable(name);
    self.foodItemList = ko.observableArray(foodItemList.map(mapFoodItem));
  
;

ko.applyBindings(new MenuWizardModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<label>Discount <input data-bind="value: commonDiscount"></label>
<label>Sub Menu Name: <input data-bind="value: newSubMenuItemName" /></label>
<button data-bind="click: addNewSubMenuItem">Add Sub Menu</button>

<div data-bind="foreach: data: menuCategories, as: 'menu' ">
  <h4 data-bind="text: menu.name"></h4>
  <div data-bind="foreach: data: menu.foodItemList, as: 'food'" class="list-group">
    <div class="list-group-item">
      Name: <span data-bind="text: food.name"></span> 
      Price: <span data-bind="text: food.price"></span>
      Discounted Price: <span data-bind="text: food.discountedPrice"></span>
    </div>
  </div>
</div>

【讨论】:

谢谢内森!...我会尽快尝试这个:)感谢您的回复!..为您提供数字啤酒:D

以上是关于如何处理绑定:更改 observableArray 中的数据后的 foreach的主要内容,如果未能解决你的问题,请参考以下文章

如何处理失败的可选绑定

WPF 如何处理对空对象属性的绑定?

当 ListView 有 ItemTemplate 时如何处理 ListViewItem 的右键单击?

如何处理视图模型属性的绑定内部数据?

如何处理 WCF 的 MSMQ 绑定中的消息失败

Envers 如何处理架构更改?