web-dev-qa-db-ja.com

ng-repeatのカスタムソート関数

ユーザーが選択したオプションに応じて特定の数を表示するタイルのセットがあります。ここで、表示されている数字に基づいて並べ替えを実行します。

以下のコードは、どのように実装したかを示しています(親カードのスコープに値を取得/設定することにより)。今、orderBy関数は文字列をとるので、curOptionValueと呼ばれるカードスコープに変数を設定し、それでソートしようとしましたが、うまくいかないようです。

質問は、カスタムソート関数を作成する方法ですか?

<div ng-controller="aggViewport" >
<div class="btn-group" >
    <button ng-click="setOption(opt.name)" ng-repeat="opt in optList" class="btn active">{{opt.name}}</button>
</div>
<div id="container" iso-grid width="500px" height="500px">
    <div ng-repeat="card in cards" class="item {{card.class}}" ng-controller="aggCardController">
        <table width="100%">
            <tr>
                <td align="center">
                    <h4>{{card.name}}</h4>
                </td>
            </tr>
            <tr>
                <td align="center"><h2>{{getOption()}}</h2></td>
            </tr>
        </table>        
    </div>
</div>

およびコントローラー:

module.controller('aggViewport',['$scope','$location',function($scope,$location) {
    $scope.cards = [
        {name: card1, values: {opt1: 9, opt2: 10}},
        {name: card1, values: {opt1: 9, opt2: 10}}
    ];

    $scope.option = "opt1";

    $scope.setOption = function(val){
        $scope.option = val;
    }

}]);

module.controller('aggCardController',['$scope',function($scope){
    $scope.getOption = function(){
        return $scope.card.values[$scope.option];
    }
}]);
108
user1167650

実際、orderByフィルターは、文字列だけでなく関数としてパラメーターとして使用できます。 orderByドキュメントから: https://docs.angularjs.org/api/ng/filter/orderBy ):

function:ゲッター関数。この関数の結果は、<、=、>演算子を使用してソートされます。

したがって、独自の関数を作成できます。たとえば、opt1とopt2の合計に基づいてカードを比較する場合(これを構成しているのは、任意の関数を使用できることです)、コントローラーに書き込みます。

$scope.myValueFunction = function(card) {
   return card.values.opt1 + card.values.opt2;
};

次に、テンプレートで:

ng-repeat="card in cards | orderBy:myValueFunction"

これが動作するjsFiddleです

もう1つ注目に値するのは、orderByAngularJSフィルター の単なる一例であるため、非常に具体的な順序付けの動作が必要な場合は、独自のフィルターを作成できます(ただし、ほとんどのユースケースではorderByで十分です)。

187

受け入れられているソリューションは配列でのみ機能し、オブジェクトまたは連想配列では機能しません。残念ながら、Angularは配列列挙のJavaScript実装に依存するため、オブジェクトプロパティの順序を一貫して制御することはできません。一部のブラウザは、オブジェクトのプロパティを辞書式に反復処理する場合がありますが、これは保証できません。

例えば次の割り当てがある場合:

$scope.cards = {
  "card2": {
    values: {
      opt1: 9,
      opt2: 12
    }
  },
  "card1": {
    values: {
      opt1: 9,
      opt2: 11
    }
  }
};

ディレクティブ<ul ng-repeat="(key, card) in cards | orderBy:myValueFunction">、ng-repeatは、ソート順序に関係なく、「card2」の前に「card1」を反復処理する場合があります。

これを回避するには、オブジェクトを配列に変換するカスタムフィルターを作成し、コレクションを返す前にカスタムソート関数を適用します。

myApp.filter('orderByValue', function () {
  // custom value function for sorting
  function myValueFunction(card) {
    return card.values.opt1 + card.values.opt2;
  }

  return function (obj) {
    var array = [];
    Object.keys(obj).forEach(function (key) {
      // inject key into each object so we can refer to it from the template
      obj[key].name = key;
      array.Push(obj[key]);
    });
    // apply a custom sorting function
    array.sort(function (a, b) {
      return myValueFunction(b) - myValueFunction(a);
    });
    return array;
  };
});

カスタムフィルターと組み合わせて(キー、値)の組み合わせを反復処理することはできないため(配列のキーは数値インデックスであるため)、注入されたキー名を参照するようにテンプレートを更新する必要があります。

<ul ng-repeat="card in cards | orderByValue">
    <li>{{card.name}} {{value(card)}}</li>
</ul>

連想配列でカスタムフィルターを使用する作業フィドルは次のとおりです。 http://jsfiddle.net/av1mLpqx/1/

参照: https://github.com/angular/angular.js/issues/1286#issuecomment-22193332

26
David

次のリンクは、Angularのフィルターを非常によく説明しています。 ng-repeat内でカスタムソートロジックを定義する方法を示しています。 http://toddmotto.com/everything-about-custom-filters-in-angular-js

プロパティを使用してオブジェクトを並べ替える場合、これは私が使用したコードです:(この並べ替えは標準のJavaScript並べ替えメソッドであり、角度に固有ではないことに注意してください)Column Nameは並べ替えが実行されるプロパティの名前です。

self.myArray.sort(function(itemA, itemB) {
    if (self.sortOrder === "ASC") {
        return itemA[columnName] > itemB[columnName];
    } else {
        return itemA[columnName] < itemB[columnName];
    }
});
7
Jonathan Cardoz

OrderBy関数とともに方向を含めるには:

ng-repeat="card in cards | orderBy:myOrderbyFunction():defaultSortDirection"

どこで

defaultSortDirection = 0; // 0 = Ascending, 1 = Descending
0
Ben