Knockout在过滤器上计算新值

时间:2014-04-29 16:05:32

标签: javascript jquery knockout.js knockout-2.0

我正在构建一个数量非常繁重的应用程序,该应用程序的一个功能是能够在最后的三个结果之间进行过滤。这些是:药物,疾病和全部(两个)。

我对Knockout很陌生,所以不能完全确定以下情况的最佳实践方法是什么。

我有值过滤,我的问题在于计算新值。 底部的总计必须反映表格中当前可见的数据。虽然下面的codepen中的这些单元格值(除了总数)是静态的,但它们在我的应用中实际上是动态的'是在前一页的应用程序中存储在sessionStorage中的几个值的计算组合。 (此屏幕是总页数。)

示例:

self.total = ko.computed(function () { return sessionStorage.getItem('1') * sessionStorage.getItem('2') });

所以要澄清;最初,表格底部的计算总数是表格单元格中的数字总和,它们是来自sessionStorage的数字的乘积。然后,每次过滤表时,总计值都需要更新,以反映可见数据的总和。

http://codepen.io/anon/pen/nlemE

我很欣赏这可能很复杂,如果我没有充分解释,请告诉我,我会澄清。

2 个答案:

答案 0 :(得分:1)

不是使用jQuery来隐藏/显示行,最好使用observableArray来存储您的值,并使用计算函数在每次过滤器值更改时过滤该数组。

这是一个更新的CodePen,展示了它的工作原理:http://codepen.io/anon/pen/HAzcf?editors=101

您的数据代码将是一个对象数组,而不是r1c1,r2c1等。我们还添加了一个过滤器字段,因此我们不必将其硬编码到HTML中。

self.values = ko.observableArray([
  {
    c1: ko.observable(10),
    c2: ko.observable(32),
    c3: ko.observable(36),
    filter: ko.observable('drugs')
  },
  {
    c1: ko.observable(70),
    c2: ko.observable(46),
    c3: ko.observable(31),
    filter: ko.observable('disease')
  }
  // etc..
]);

我们的切换功能现在只是更新一个可观察的:

// toggle
self.filter = ko.observable('all');
self.toggleVis = function (data, event) {
    self.filter(event.target.value);
};

每次更新self.filter observable时,都会更新过滤后的值:

self.filteredValues = ko.computed(function() {
    var filter = self.filter();
    return ko.utils.arrayFilter(self.values(), function(item) {
        return filter == 'all' || item.filter() == filter;
    }); 
});

每当更改filteredValues时,我们的总计属性都会更新:

self.total1 = ko.computed(function () {
    var total = 0,
        values = self.filteredValues();
    for(var i = 0; i < values.length; i++) {
        total += values[i].c1();
    }
    return total;
});

您的HTML表格代码也变得简化,只是迭代过滤的可观察数组:

<table>
  <tbody>
    <!-- ko foreach: filteredValues -->
    <tr class="row">
      <td data-bind="text:c1"></td>
      <td data-bind="text:c2"></td>
      <td data-bind="text:c3"></td>
    </tr>
    <!-- /ko -->
    <tr class="totals">
      <td data-bind="text:total1"></td>
      <td data-bind="text:total2"></td>
      <td data-bind="text:total3"></td>
    </tr>
  </tbody>
</table>

答案 1 :(得分:0)

您希望在每个可观察对象上使用Knockout Subscription

self.r1c1().subscribe(function(newValue) {
    // update the sum
});

但是,您可能希望使用Knockout Observable Array来存储/更新各个值,而不是添加20个订阅。

var myObservableArray = ko.observableArray();    
myObservableArray.push(<value for row 1>);
myObservableArray.push(<value for row 2>);
// etc

然后,您可以通过单个订阅获得三列中的每一列。

self.myObservableArray.subscribe(function(newValue) {
    // re-calculate the sum of the values
});