1

私はMVVMパターンbreeze.jsとknockout.jsを使用してMVCWebアプリケーションに取り組んでいます。これらのjsライブラリを使用するのはこれが初めてですが、それでもそれらがどのように機能するかを把握する必要があります。

アプリケーションのページの1つには、列と行の両方が動的に生成されるグリッドがあります。列を追加する必要があります。各行について、次の行のセルに値の合計が表示されます。ここに例があります:

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

グリッドは、そよ風のエンティティオブジェクト(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という名前のノックアウト計算されたオブザーバブルを追加することによってエンティティを拡張することです。この関数は、そよ風の観測可能な配列FactValuesを反復処理し、値を追加します。私はこのコードのさまざまなバージョンをいじくり回していて無駄にしています。誰かがこのコードの何が問題になっているのかについてのヒントを教えてもらえますか?

4

2 に答える 2

1

アップデート:

前回の投稿で投稿したコードを機能させることができませんでした。最終的に、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 コードで次のように参照されます。

<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);
  }
};
于 2012-12-18T10:04:56.777 に答える
0

あなたのコードを Breeze の外でモデル化しましたが、動作しています:

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

JavaScript のループ/この問題を克服するために、コンストラクターに FactValues (observableArray) への参照を追加する小さな調整を行いました。

しかし、私はこれを Breeze で試したことがなく、似たようなことをしたいと思っていました。同様の関数を機能させることができず、最終的に、executeQuery の「その後」の処理中に合計を作成しました。

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

今日はこのバージョンの作業に戻ろうとします。より良い解決策を見つけたら、また報告します。

于 2012-12-14T17:41:28.073 に答える