如何使用breeze.js扩展实体计算网格中的总数?

时间:2012-12-14 13:36:04

标签: model-view-controller mvvm knockout.js breeze computed-observable

我正在使用MVVM模式breeze.js和knockout.js开发MVC Web应用程序。这是我第一次使用这些js库,我仍然需要掌握它们的工作原理。

该应用程序的一个页面有一个网格,其中列和行都是动态生成的。我需要添加一个额外的列,其中每行我都有以下行单元格中显示的总值。这是一个例子:

Data type |   Comment   |  Fact 1 | Fact 2 |  Total    | Value 1 | Value 2 | Value 3 | Value 4
==============================================================================================
Item 1    | any comment |  fact 1 | fact 2 | calc. sum |    10   |   20    |    30   |   40

通过将breeze实体对象(planningItems)绑定到模板来生成网格。该对象具有DataTypeId,Comment,Member,Total,FactValues属性。总计是计算的总和。

<script type="text/html" id="list-planning-template">
<tr data-bind="mouseOverButton: $data">
    <td style="text-align: center">
        <button class="actionbutton actionbutton-item" data-bind="selectItem: $root.selectedItems, itemId: FactId"></button>
    </td>
    <td data-bind="text: DataTypeId" />
    <td data-bind="text: Comment().Text" />
    <!-- ko foreach: FactMembers -->
    <td data-bind="text: Member().Code"></td>
    <!-- /ko -->
    <td data-bind="text: Total" />
    <!-- ko foreach: FactValues -->
    <td style="width: 50px" data-bind="text: Value"></td>
    <!-- /ko -->
</tr>

我一直试图通过以下列方式扩展breeze实体对象来添加Total属性:

var FactCtor = function () {
this.Total = ko.computed({
    read: function () {
        var sum = 0;
        if (this.FactValues) {
            this.FactValues().forEach(function (fv) {
                sum += fv.Value();
            });
        }
        return sum;
    },
    deferEvaluation: true
}, this);
};

manager.metadataStore.registerEntityTypeCtor("Fact", FactCtor);

本质上,此代码应该做的是通过添加具有延迟评估的名为Total的挖空计算可观察对来扩展实体。该函数遍历breeze可观察数组FactValues并添加值。我一直在捣乱这个代码的不同版本无济于事。任何人都可以给我一个关于这段代码有什么问题的提示吗?

2 个答案:

答案 0 :(得分:1)

<强>更新

我们无法获取上一篇文章中发布的代码。我们最终能够通过使用微风自定义绑定来克服这个问题。这是代码:

   ko.bindingHandlers.getFyTotal = {
   update: function (element, valueAccessor) {
       var sum = 0;
       var fact = valueAccessor();
       if (fact.FactValues()) {
           fact.FactValues().forEach(function (fv) {
               sum += parseFloat(fv.Value());
           });
       }

       $(element).html(sum);
   }
};

然后通过以下方式在HTML代码中引用自定义绑定:

<td data-bind="getFyTotal: $data" />

希望这可以帮助别人。

修订版本

我们已更新上述代码以利用ko.utils函数:

ko.bindingHandlers.getFyTotal = {
update: function (element, valueAccessor) {
    var sum = 0;
    var fact = valueAccessor();
    if (fact.FactValues()) {
        ko.utils.arrayForEach(fact.FactValues(), function (fv) {
            sum += parseFloat(fv.Value());
        });
    }

    $(element).html(sum);
  }
};

答案 1 :(得分:0)

我在Breeze之外建模你的代码并且它正在运行:

http://jsfiddle.net/DazWilkin/yGZ7g/7/

我在构造函数上添加了对FactValues(observableArray)的引用进行了一些小调整,以克服我认为是JavaScript中的循环/此问题。

但是,我没有在Breeze中尝试这个并想做类似的事情。我无法获得类似的功能,最终在我的executeQuery'then'处理过程中创建了总数:

...manager.executeQuery(....).then(function(data) {
   ...
   Fact.Total(FactValues()
      .map(function(fv){ return fv.Value(); })
      .reduce(function (total,curr) { return total+curr; });
   ...
}

我今天会尝试回到我的版本,如果我找到更好的解决方案,我会报告回来。