programing

AngularJS에서 배열이 아닌 개체 맵에서 필터링

elecom 2023. 10. 25. 22:35
반응형

AngularJS에서 배열이 아닌 개체 맵에서 필터링

$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>

데이터 구조를 배열로 변경합니다.어쨌든 여기 친구 개체를 필터링하는 다른 구현이 있습니다.

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;
    };
  });

이는 개체에 대해 한 번만 반복되며 비교됩니다.name그리고.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

'필터'로 직접 할 수는 없겠군요.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

아마도 더 나은 해결책은 맞춤 필터를 작성하는 것입니다.

저도 같은 문제가 있었는데, 실제 매칭을 하기 위해 내장된 필터를 사용하면서 지도를 받아들이는 필터를 직접 만들어 성공했습니다.

사용자 지정 필터는 맵을 통과하고 각 요소에 대해 내장 필터를 호출하지만 해당 필터는 배열만 허용하므로 각 요소를 길이 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개 요소가 포함된 지도에서 필터링이 여전히 즉각적으로 수행됩니다.

개체를 배열로 변경하지 않는 방법에 대해 예를 들어봤습니다.이것이 질문에 대한 답을 더 정확하게 하는 것 같습니다.

개체에서 검색할 수 없는 문제가 있었습니다.

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;
    };
  });

배열을 반환하는 대신 개체를 반환합니다.

누군가에게 도움이 되길 바랍니다!

최적의 솔루션은 아니지만 빠르고 더러운 것을 원하는 경우:

<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

필터를 사용하는 대신 간단히 다음을 수행할 수도 있습니다.

$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>

언급URL : https://stackoverflow.com/questions/13887504/filtering-on-object-map-rather-than-array-in-angularjs

반응형