24

以下のような配列ではなく、他のプロパティを持つオブジェクトである $scope プロパティを持つコントローラーが与えられた場合、ng-repeatセットをどのようにフィルター処理する必要がありますか?

ここにJSFiddleがあります:http://jsfiddle.net/ZfGx4/110/

コントローラ:

function HelloCntl($scope, $filter) {
    $scope.friends = {
        john: {
            name: 'John',
            phone: '555-1276'
        },
        mary: {
            name: 'Mary',
            phone: '800-BIG-MARY'
        },
        mike: {
            name: 'Mike',
            phone: '555-4321'
        },
        adam: {
            name: 'Adam',
            phone: '555-5678'
        },
        julie: {
            name: 'Julie',
            phone: '555-8765'
        }
    };
}​

テンプレート:

<div ng:app>
 <div ng-controller="HelloCntl">
  <input placeholder="Type to filter" ng-model="query">     
  <ul>
   <li ng-repeat="(id, friend) in friends | filter:query">
    <span>{{friend.name}} @ {{friend.phone}}</span>
   </li>
  </ul>
 </div>
</div>
4

6 に答える 6

25

データ構造を配列に変更します。とにかく、友達オブジェクトをフィルタリングする別の実装を次に示します。

angular.module('filters',['utils'])
  .filter('friendFilter', function(utils){

    return function(input, query){
      if(!query) return input;
      var result = [];

      angular.forEach(input, function(friend){
        if(utils.compareStr(friend.name, query) ||
           utils.compareStr(friend.phone, query))
          result.push(friend);          
      });
      return result;
    };
  });

これは、オブジェクトを 1 回だけ反復し、nameandで比較し、phoneこのように呼び出すことができます。

<li ng-repeat="friend in friends | friendFilter:query">

別のモジュールでを定義しcompareStrましたが、実際に行う必要はありません。

angular.module('utils', [])
  .factory('utils', function(){
    return{
      compareStr: function(stra, strb){
        stra = ("" + stra).toLowerCase();
        strb = ("" + strb).toLowerCase();
        return stra.indexOf(strb) !== -1;
      }
    };
  });

filtersモジュールをアプリに挿入することを忘れないでください

angular.module('app',['filters'])

完全な例は次のとおりです: http://jsbin.com/acagag/5/edit

于 2012-12-15T04:17:38.467 に答える
13

「フィルター」で直接行うことはできないと思います。angular.js のコードを見ると、これらはフィルター関数の最初の行です。

function filterFilter() {
  return function(array, expression) {
    if (!(array instanceof Array)) return array;

したがって、配列とは異なるものを受け取った場合、何もしません。

推奨するかどうかはわかりませんが、アイデアは次のとおりです。

コントローラーでは、フィルターに渡す前に配列に変換するだけです。

$scope.filteredFriends = function() {
    var array = [];
    for(key in $scope.friends) {
        array.push($scope.friends[key]);
    }
    return $filter('filter')(array, $scope.query);
}

そしてng-repeat:

<li ng-repeat="friend in filteredFriends()">

例: http://jsbin.com/acagag/2/edit

おそらく、より良い解決策は、カスタム フィルターを作成することです。

于 2012-12-15T00:51:01.910 に答える
3

私は同じ問題を抱えていましたが、マップを受け入れる独自のフィルターを作成することで成功しましたが、実際のマッチングには組み込みフィルターを使用しました。

カスタム フィルターはマップを走査し、要素ごとに組み込みフィルターを呼び出しますが、そのフィルターが配列のみを受け入れることを考えると、各要素を長さ 1 の配列 (以下の [データ]) でラップします。したがって、出力配列の長さが 1 のままであれば、一致は成功します。

.filter('mapFilter', function($filter) {
  var filter = $filter('filter');

  return function(map, expression, comparator) {
    if (! expression) return map;

    var result = {};
    angular.forEach(map, function(data, index) {
      if (filter([data], expression, comparator).length)
        result[index] = data;          
    });

    return result;
  }
})

もちろん、このセットアップは効率を失います。これは、すべての要素を含む配列を与える場合に一度だけではなく、マップ内の各要素に対して何をする必要があるかを判断するために組み込みフィルターが必要になるためです。私の場合はマップを使用します。 500 要素の場合でも、フィルタリングは瞬時に行われます。

于 2014-06-08T10:06:10.033 に答える
1

オブジェクトを配列に変更しない方法の例を作成しました。これは質問にもっと正しく答えると思います。

オブジェクトを検索できないという同じ問題がありました。

http://jsbin.com/acagag/223/edit

angular.module('filters',['utils'])
  .filter('friendFilter', function(utils){

    return function(input, query){
      if(!query) return input;
      var result = {};

      angular.forEach(input, function(friendData, friend){
        if(utils.compareStr(friend, query) ||
           utils.compareStr(friendData.phone, query))
          result[friend] = friendData;          
      });
      return result;
    };
  });

したがって、配列を返す代わりに、オブジェクトを返します。

これが誰かを助けることを願っています!

于 2014-03-20T14:39:47.267 に答える
1

最適な解決策ではありませんが、迅速で汚いものが必要な場合:

<li ng-repeat="(id, friend) in friends | filter:query" ng-hide="id !== query.id">
  <span>{{friend.name}} @ {{friend.phone}}</span>
</li>

またはng-if代わりにng-hide

于 2015-02-22T21:26:32.217 に答える
0

フィルターを使用する代わりに、次のことも簡単に行うことができます。

$http.get('api/users').success(function(data){
    angular.forEach(data, function(value, key){
        users.push(value);
    });
    $scope.users = users;
});

そしてテンプレに

<input type="text" ng-model="query" placeholder="Search user"/>

<li ng-repeat="user in users | filter:query">
    {{ user.name }}
</li>
于 2014-06-06T09:30:35.153 に答える