简体   繁体   中英

knockout foreach binding with a function

Consider the following code:

<div class="expandedCoverages" data-bind="foreach: $root.getGroupCoveragesPerPackage(packageCost)">
  <div class="calculateCostCoverage" 
         data-bind="html: CoverageGroupDescription()"></div>
  </div>
</div>

If packageCost observable changes, CoverageGroupDescription() doesn't change since function isn't triggered again.

Is it possible somehow to trigger again the function so as to change the foreach binding?

Under the hood this is what Knockout does with functions/ statements executed directly in the view (HTML):

  • If the code does not depend on an observable , it will be evaluated only once.
  • If the code depends on an observable , it will create a computed observable that will re-evaluate every time that observable changes.

Although using a computed property in the JS model, like Sam C.'s comment suggests, is cleaner, it is not absolutely necessary. Doing:

<div data-bind="foreach: myFunction(observableParam())"></div>

is actually the same as doing:

<div data-bind="foreach: myComputed"></div>

with:

this.myComputed = ko.computed(function() { return myFunction(observableParam()); });

That means in this case probably coverageGroupDescription does not return a correctly updated array. See a working example with a more or less similar implementation as in the question, below. Change the packageCost and the descriptions will automatically change too.

 var Coverage = function(cost) { this.cost = ko.observable(cost); this.coverageGroupDescription = function() { return 'This package costs ' + this.cost() + '$'; }.bind(this); } var app = { items: ko.observableArray([ new Coverage(15), new Coverage(20), new Coverage(25), new Coverage(30), new Coverage(35), ]), packageCost: ko.observable(1), getGroupCoveragesPerPackage: function(m) { var m = m(); return ko.utils.arrayMap(this.items(), function(item, i) { return new Coverage(item.cost()*m); }); } }; ko.applyBindings(app); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script> Multiply all by: <input type="text" data-bind="value: packageCost"> <ul data-bind="foreach: getGroupCoveragesPerPackage(packageCost)"> <li data-bind="text: coverageGroupDescription()"></li> </ul> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM