0

I am altering an observableArray, modifying some data in a subscribe event. First I am converting the ObservableArray using ko.toJS(), mapping trough the data, and altering. At the end I call self.menuCategories(jsArray) to set the observableArray again.

It seems like I lose the "connection" to the observableArray in some way, since the foreach statement in my code suddenly breaks.

Either there is a very much easier way to handle this, or I am not handling the observables correctly.

CODE :

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);
    });

MARKUP :

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

DATA :

enter image description here

1 Answer 1

1

I think the best way to handle this type of thing is to add a computed observable to the fooditem that captures the global discount and calculates the discounted price.

something like the following.

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>

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks Nathan!.. I will try this as quicky as i can :) Appreciate your response!.. Digital Beer for you :D

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.