2013-11-27 4 views
8

フィルタのオブジェクトに変換を適用しようとしています。その結果、新しいオブジェクトの配列が返されます。これは、変換が適用された後にオブジェクトをフィルタリングし、変換の結果を表示するためです。しかし、私が表示するオブジェクトは、($$idsを比較すると)入れたオブジェクトとは異なるため、無限のダイジェストになります。AngularJs - ng新しいオブジェクトを返すフィルタを使用して返す

  1. track by item.idのような追跡式を使用して変換したオブジェクトのそれぞれに、元のオブジェクトのidsを割り当てます。これは以下の通りを解決するために私の考え。すべてのオブジェクトに現在idが含まれていますが、フィルタはあまり一般的ではなく、idである必要があります。変換はid(上書きされます)などに設定してはいけません。

  2. 変換オブジェクトに元のオブジェクトの$$idを割り当てます。これは私の理解に基づいて、ハックアップしているようです$$idは読んでいると仮定されています。

  3. 変換のフィルタリングの結果に基づいて元のオブジェクトのサブセットを返します。これは、変換がフィルタと表示式の両方に適用される必要があるため、変換された/フィルタ処理されたアイテムをループバックして、元のものを選択して戻す必要があるため、パフォーマンスの問題を引き起こす可能性があります。

    <tr ng-repeat="item in list.items | ui.filter.transformFilter:list.transformerFunction:list.search" ng-click="list.select({'item': item})" class="list-item"> 
        <td ng-repeat="label in list.labels" ng-bind-html="item[label.key]"></td> 
        </tr> 
    

    ああ、元のオブジェクトを返しますngClick理想的に、私は次のことができます。

    listModule.filter('ui.filter.transformFilter', 
           ['$filter', 
            '$id', 
            function($filter, $id) 
        { 
        var Filter = $filter('filter'); 
        return function(objects, transformer, expression) { 
         // precondition- we need a list of objects 
         if (!_.isArray(objects)) { 
         return objects; 
         } 
    
         var transformed = []; 
         for (var i = 0; i < objects.length; i++) { 
         transformed[i] = transformer(objects[i]); 
         } 
    
         return filtered = Filter(transformed, expression); 
        }     
        }] 
    ); 
    

    そして、ここでは、私はそれを使用しようとしています方法です。ここで

はフィルタであり、それを見るために常に関数をラップします。

+0

Fiddle?プランカ? – Stewie

+0

私は解決策を知っていると思います:)私はそれに取り組んでいます。 – m59

+0

'list.labels'のサンプルデータがありますか? – m59

答えて

2

角度範囲の変更を検出するために角度使用angular.equalsを使用します。トラッキング式は配列要素をDOM要素と照合するために使用されるため、配列をフィルタまたは並べ替えると、Angularはサブツリー全体を再構築するのではなく、いくつかの要素を表示、非表示、並べ替えます。

は、この単純な例を見てください:問題なくng-init作品内で同じことをしながら、フィルタによって項目を変更http://jsfiddle.net/Nb8mX/

function Ctrl($scope) { 

    $scope.transform = function(item) { 
     item.abc *= 2; 
     return true; 
    }; 

    $scope.data = [ 
     {abc: 123, def: 1}, 
     {abc: 456, def: 2}, 
     {abc: 789, def: 3} 
    ]; 

} 

は、関係なく、track byの無限ダイジェストループが発生します。

<ul ng-app="blah" ng-controller="Ctrl"> 
    <li ng-repeat="item in data | filter : transform">{{ item.abc }}</li> 
    <li ng-repeat="item in data | filter : transform track by item.def">{{ item.abc }}</li> 
    <li ng-repeat="item in data" ng-init="transform(item)">{{ item.abc }}</li> 
</ul> 

これは、フィルタではなくディレクティブを記述できることを示しています。

誰かがもっと良い解決策を知っていれば、私もそれを学ぶのがうれしいでしょう。

7

あなたは、オブジェクトIDによる、角度が冪等されていないと考えるべき等の機能を持たせてこの問題の解決策の1つ(したがって原因を$あなたが述べたようにループ問題をダイジェスト)使用LO-ダッシュ/アンダースコアの_.memoizeにありますあなたの関数の結果をキャッシュする

これにより、任意のキャッシュキーに対して、フィルタは常に完全に同一のオブジェクト($$idを含む)を返すことが保証されます。この方法では、$$idでゲームをプレイする必要はなく、各$ digestループにフィルタの結果を再計算する必要がないという利点がになります。ここで

はあなたのフィルタの結果をキャッシュできる方法です:あなたの状況について

return _.memoize(function(objects, transformer, expression) { ... }, 
       function(objects,transformer,expression){ 
        return objects +transformer.name + expression; 
        }); 

一つの重要なノートでは、デフォルトで_.memoizeはキャッシュキーとして(この場合はobjects)最初の関数のパラメータを使用していることです。異なるトランス関数と式で異なるフィルタ結果が得られる可能性があるので、オプションの第2パラメータ - objectsexpression、およびキャッシュキーを生成するtransformer関数の名前を使用するハッシュ関数を追加しました。

コードを次のように簡略化したものです。fiddle

関連する問題