ユーザーが選択したオプションに応じて特定の数を表示するタイルのセットがあります。ここで、表示されている数字に基づいて並べ替えを実行します。
以下のコードは、どのように実装したかを示しています(親カードのスコープに値を取得/設定することにより)。今、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];
}
}]);
実際、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"
もう1つ注目に値するのは、orderBy
は AngularJSフィルター の単なる一例であるため、非常に具体的な順序付けの動作が必要な場合は、独自のフィルターを作成できます(ただし、ほとんどのユースケースではorderBy
で十分です)。
受け入れられているソリューションは配列でのみ機能し、オブジェクトまたは連想配列では機能しません。残念ながら、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
次のリンクは、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];
}
});
OrderBy関数とともに方向を含めるには:
ng-repeat="card in cards | orderBy:myOrderbyFunction():defaultSortDirection"
どこで
defaultSortDirection = 0; // 0 = Ascending, 1 = Descending