37

一部のフィールドが空であるか、値がないことを除いて、データとその動作はすべて正しいです。注文すると、これらの空のフィールドが最初に表示されます。たとえば、数値を並べ替えると、「0」値を取得する前に巨大な空のリストが取得されます。

私はこのようにやっています:

ng-click="predicate = 'name'; reverse=!reverse"

ng-repeat="name in names | orderBy:predicate:reverse"

JSFiddle: http://jsfiddle.net/JZuCX/1/

これを修正する簡単でエレガントな方法はありますか? 何があっても、空のフィールドが最後になるようにします。

4

9 に答える 9

63

文字列をソートするためにこれはどうですか:

item in (items|orderBy:['!name', 'name'])

利点は(より簡潔になることを除けば)、空白文字列でソートされることnullです。undefined

私の場合、空白とnullと未定義を一緒に上部に配置したかったので(デフォルトではnullと未定義は下部にソートされます)、次を使用しました:

item in (items|orderBy:['!!name', 'name'])
于 2015-10-22T16:41:31.893 に答える
43

順序付けられた配列から空の名前の項目を取得し、最後に配置するフィルターを作成します。

<li ng-repeat="item in (items|orderBy:'name'|emptyToEnd:'name')">{{item.name}}</li>

コードは次のようになります。

.filter("emptyToEnd", function () {
    return function (array, key) {
        if(!angular.isArray(array)) return;
        var present = array.filter(function (item) {
            return item[key];
        });
        var empty = array.filter(function (item) {
            return !item[key]
        });
        return present.concat(empty);
    };
});

実施例

ところで、フィドルには関連するコードが含まれていません。間違ったリンクを使用しましたか?

更新 2: 私のフィルターをいじってください。

于 2013-09-04T02:55:21.970 に答える
4

Klaster_1 のソリューションに加えて、追加のパラメーターを追加して、フィルターをより汎用的にします。

http://jsfiddle.net/Zukzuk/JZuCX/27/

実装

<tr ng-repeat="name in (names | orderBy:predicate:reverse | orderEmpty:'name':'toBottom')">

フィルター

.filter('orderEmpty', function () {
    return function (array, key, type) {
        var present, empty, result;

        if(!angular.isArray(array)) return;

        present = array.filter(function (item) {
            return item[key];
        });

        empty = array.filter(function (item) {
            return !item[key]
        });

        switch(type) {
            case 'toBottom':
                result = present.concat(empty);
                break;
            case 'toTop':
                result = empty.concat(present);
                break;

                // ... etc, etc ...

            default:
                result = array;
                break;
        }
        return result;
    };
});

さすがKlaster_1!

于 2015-01-15T12:35:05.763 に答える
4

これには「すぐに使える」ソリューションがあるとは思いません。私は簡単に間違っている可能性があります。関数を述語として使用するソリューションの私の試みは次のとおりです。

ng-repeat="name in names | orderBy:predicate"

コントローラーの内部:

$scope.predicate = function(name) {
    return name === '' ? 'zzzzzzz' : !name; 
    /* The 'zzzzzz' forces the empty names to the end, 
      I can't think of a simpler way at the moment. */
}
于 2013-09-04T03:03:24.433 に答える
2

変数の並べ替え列を使用して、並べ替えと逆の並べ替えを行い、負の値の下であっても未定義を一番下に保持する

上記のショーンの答えの優雅さが大好きです!ユーザーが並べ替える列を選択し、並べ替え方向を選択できるようにする必要がありましたが、負の数がある場合でも、未定義のものを一番下に配置する必要があります。

負の数を修正する Sean の重要な洞察は !! です。順ソートを行う場合は「!」+述語を使用し、逆ソートを行う場合は「!!」+述語を使用します。

以下のスニペットはこれを示しています。ところで、奇妙なスコープの問題が発生しないように、述語 (並べ替えるプロパティの選択) を設定し、オブジェクト ("d") 内で反転する変数を配置しました。お使いの環境では「d.」は必要ない場合があります。

さらに、ソート述語と方向を制御するために、ページの下部にある私のくだらないボタンよりも優れたものを使用することをお勧めします。ただし、これにより、コードの重要な部分が読みやすくなります。

function mainController($scope) {
  $scope.userArray = [
  { name: "Don", age: 20 },
  { name: "Bob", age: 30, height: 170 },
  { name: "Abe", age: 40, height: 160 },
  { name: "Zoe", age: 70 },
  {              age: 70, height: 155 },
  { name: "Shorty",age:45,height: -200},
  { name: "TwinkleInEye", age: -1, height: 152 }
  ]

  $scope.d = {}; // Create an object into which info can be stored and not trashed by Angular's tendency to add scopes
  $scope.d.predicate = "name"; // This string is the name of the property on which to sort
  $scope.d.reverse = false; // True means reverse the sort order
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<body ng-app="" ng-controller="mainController">
  <div ng-repeat="user in (userArray | orderBy: (d.reverse ?['!!'+d.predicate,d.predicate]:['!'+d.predicate,d.predicate]) : d.reverse)">

    Name {{ user.name }} : Age {{ user.age }} : Height {{ user.height }}
  </div>

  <br/>

  <button ng-click="d.predicate='name';">Name</button>
  <button ng-click="d.predicate='age';">Age</button>
  <button ng-click="d.predicate='height';">Height</button> Currently: {{d.predicate}}
 <br/> Leave undefined at bottom, but otherwise: 
  <button ng-click="d.reverse= !d.reverse;">Reverse</button> Currently: {{d.reverse}}

</body>

于 2017-03-19T15:17:24.957 に答える
0

@Klaster_1 は本当に何かに取り組んでいましたが、ネストされた値が必要になるとすぐにフィルターが機能しなくなりました。また、逆順の場合でも、null 値が 0 より前に表示されるようにしたいと考えていました。ネストされたキーを処理するために $parse を追加し、null 値を一番上に配置するタイミングを知っているに reverse パラメーターを追加しました。

.filter("emptyToEnd", function ($parse) {
    return function (array, key, reverse) {
        if(!angular.isArray(array)) return;
        var keyFn = $parse(key);
        var present = [];
        var empty = [];

        angular.forEach(array, function(item){
          var val = keyFn(item);
          if(angular.isUndefined(val) || val === null) {
            empty.push(item);
          } else {
            present.push(item);
          }
        });

        if (reverse) {
          return present.concat(empty);
        } else {
          return empty.concat(present);
        }
    };
});
于 2014-07-10T22:04:43.213 に答える
0

他の回答が null 値のレコードを一番下に配置することを提案している理由がわかりません。通常どおりに並べ替えたい場合は、ASC 順ですべての null を上に、DESC 順ですべての null を一番下に配置することを意味します。他の回答を試しましたここでしかし、私を助けることができなかったので、私の配列でヌルを '' に変換するようにコードを変更すると、次のようにスムーズに動作するようになりました:

$scope.convertNullToBlank = function (array) {
  for (var i = 0; i < array.length; i++) {
     if (array[i].col1 === null)
       array[i].col1 = '';

     if (array[i].col2 === null)
        array[i].col2 = '';
  }
  return array;
}
于 2015-09-08T14:39:46.420 に答える