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

Model view controller 如何使用breeze.js扩展实体计算网格中的总数?,model-view-controller,mvvm,knockout.js,breeze,computed-observable,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 ========

我正在使用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属性。Total是计算出的总和

<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>

本质上,这段代码应该做的是通过添加一个名为Total的敲除计算可观测值(具有延迟求值)来扩展实体。该函数遍历breeze可观察数组FactValues并添加值。我一直在胡闹这个代码的不同版本,但都没有用。有谁能告诉我这段代码有什么问题吗?

我在Breeze之外为您的代码建模,它正在工作:

我做了一个小小的调整,在构造函数中添加了对FactValues(observableArray)的引用,以克服JavaScript中的循环/这个问题

然而,我还没有在微风中尝试过这个,我想做一些类似的事情。我无法使用类似的函数,最终在执行任务的“then”处理过程中创建了总计:

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

今天我将尝试重新编写我的版本,如果我找到更好的解决方案,我将向您汇报。

我在Breeze之外为您的代码建模,它正在工作:

我做了一个小小的调整,在构造函数中添加了对FactValues(observableArray)的引用,以克服JavaScript中的循环/这个问题

然而,我还没有在微风中尝试过这个,我想做一些类似的事情。我无法使用类似的函数,最终在执行任务的“then”处理过程中创建了总计:

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

今天我将尝试重新编写我的版本,如果我找到更好的解决方案,我将向您汇报。

更新:

我们无法让我在上一篇文章中发布的代码正常工作。我们最终通过使用breeze的自定义绑定解决了这个问题。代码如下:

   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代码中以以下方式引用自定义绑定:

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);
<td data-bind="getFyTotal: $data" />

更新:

我们无法让我在上一篇文章中发布的代码正常工作。我们最终通过使用breeze的自定义绑定解决了这个问题。代码如下:

   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代码中以以下方式引用自定义绑定:

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);
<td data-bind="getFyTotal: $data" />

我的怀疑是,计算结果不是由数组内部或其内容的更改触发的。仅当更改
FactValues
属性本身时,才会触发计算结果。
FactValues
是一个数组。即使数组内容发生变化,它也始终是相同的数组。正如我所说,我只是在猜测。如果我的猜测是正确的,那么还有一条前进的道路……通过监听数组的更改(添加/删除)并在值出现或消失时触发计算值的刷新。你可以试试。我现在忙得不可开交,但如果有人在一天左右没有解决这个问题,我会爱你的。谢谢你的回答,沃德。通过使用自定义绑定,我们能够克服这个问题。有关详细信息,请参阅我的后续文章。我怀疑计算结果不是由数组内部或其内容的更改触发的。仅当更改
FactValues
属性本身时,才会触发计算结果。
FactValues
是一个数组。即使数组内容发生变化,它也始终是相同的数组。正如我所说,我只是在猜测。如果我的猜测是正确的,那么还有一条前进的道路……通过监听数组的更改(添加/删除)并在值出现或消失时触发计算值的刷新。你可以试试。我现在忙得不可开交,但如果有人在一天左右没有解决这个问题,我会爱你的。谢谢你的回答,沃德。通过使用自定义绑定,我们能够克服这个问题。详情请看我的后续帖子。谢谢你的回答,达兹威尔金。有趣的是,这些代码适合您。在我们的例子中,当breeze试图查询数据时,它失败了。最终,我们通过使用breeze的自定义绑定解决了这个问题。有关详细信息,请参阅我原始帖子中的更新。谢谢你的回答,达兹威尔金。有趣的是,这些代码适合您。在我们的例子中,当breeze试图查询数据时,它失败了。最终,我们通过使用breeze的自定义绑定解决了这个问题。有关详细信息,请参阅我的原始帖子中的更新。