AngularJS | 리스트 필터 | 커스텀 리스트 필터


기본적으로 제공되는 리스트 필터는 그리 많지는 않다. 그래도 정규 표현식을 사용할 수 있으므로 “패턴을 쓰면 대략적인 가능하다"라고 생각할 있다. 다만, 정규 표현식의 패턴을 이것 저것 지정한다고 하면, 그렇게 사용하기 쉽다고만은 할 수는 없다.

또한 간단한 값이 아닌 복잡한 구조의 객체를 배열에 정리해 경우는 객체에 따라 필요한 값을 꺼내어 확인하는 것과 같은 필터가 필요하다.

이러한 경우 필터를 추가하여 사용하는 옵션도 있다. 텍스트 필터뿐만 아니라, 리스트 필터도 직접 만들 수 있다. 이는 다음과 같이 만든다.

컨트롤러.filter(이름, 함수);

텍스트 필터와 같다. 그러나 준비하는 함수는 조금 다르다. 이는 다음과 같다.

function() {
  return function(인수) {
    ...... 인수의 배열을 조작한다 ......
    return 배열;
  }
}

함수에는 추가로 return하도록 되어 있다. 이 return되는 함수가 필터를 해서 실행되는 처리이다.

이 필터용 함수는 인수를 1개 준비된다. 이는 데이터의 배열이 전달된다. 이 배열을 바탕으로 새로운 배열을 만들고, 그것을 return하면 그 배열을 바탕으로 ng-repeat 반복이 실행되게 되는 것이다. 즉, 어떻게 새로운 배열을 만들 것인가를 생각해서 함수를 만들면 된다는 것이다.

목록 필터 생성

그러면 간단한 리스트 필터를 만들어서, 그 필터를 이용한 예제 스크립트에서 만들어 보자. script.js를 아래와 같이 작성하여 저장한다.

var myapp = angular.module('myapp',[]);
var helo = myapp.controller('HeloController',
    function() {
        this.count = 0;
        this.data = [
            { id:0, name:'no data',price:0,get:false },
            { id:1, name:'Android phone', price:7800, get:true },
            { id:2, name:'New iPhone', price:549020, get:true },
            { id:3, name:'windows phone', price:38765, get:true },
            { id:4, name:'firefox phone', price:14370, get:true },
            { id:5, name:'blackberry phone', price:-123, get:false },
        ];
        this.getData = function() {
            return this.data[this.count].id + ': ' + 
                this.data[this.count].name + ', ' + 
                this.data[this.count].price + '.';
        };
    }
);
 
//get을 체크하여, true인 경우만 반환한다.
helo.filter('getRepeat', 
    function() {
        return function(items) {
            var res = [];
            angular.forEach(items,function(item) {
                if (item.get)
                    res.push(item);
            });
            return res;
        };
    }
);

이번에는 HeloCotroller 컨트롤러에 getRepeat라는 리스트 필터를 작성하였다. 필터에 return되는 함수 부분을 보면 다음과 같이 되어 있다.

function (items) {
  var res = [];
  angular.forEach (items, function (item) {
    if (item.get)
        res.push (item);
  });
  return res;
};

여기에서는 인수로 전달된 items에서, get 메소드가 true의 것만을 배열에 정리하여 반환한다. 배열의 반복 처리를 실시하는데, angular 객체의 forEach 라는 것을 사용하고 있다.

angular.forEach(배열, 함수);

이 forEach는 첫번째 인수의 배열에서 순서대로 요소를 얻어내고, 두번째 인수의 함수를 실행하고 있다. 얻어온 요소는 함수에 인수로 전달된다. 함수에는 이 인수를 사용하여 배열의 모든 요소에 대해 처리할 수 있도록 되어 있는 것이다.

커스텀 필터 이용

그럼, 만든 필터 “getRepeat"를 사용해 보자. HTML 파일을 아래와 같이 작성한다.

<!DOCTYPE html>
<html>
<head>
    <title>AngularJS Sample</title>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
    <script src="script.js"></script>
    <style>
    body { color:gray; }
    h1 { font-size:18pt; font-weight:bold; }
    span.label { display:inline-block;width:50px; color:red; }
    input { width:100px; }
    .msg { font-size:14pt; font-weight:bold;color:gray; }
    th { color:#eee; background-color:#999; padding: 5px 10px;}
    td { color:#333; background-color:#ddd; padding: 5px 10px;}
    </style>
</head>
<body ng-app="myapp" ng-init="num=0">
    <h1>데이터 표시</h1>
    <p>텍스트를 입력해 주세요.</p>
    <div ng-controller="HeloController as ctl">
     
    <div class="input">
        <span class="label">검색:</span>
        <input type="text" ng-model="fstr">
    </div>
    <p class="msg">{{ctl.getData()} }</p>
    <hr/>
    
    <table>
    <tr><th>ID</th><th>NAME</th><th>PRICE</th><th>GET?</th></tr>
    <tr ng-repeat="obj in ctl.data | filter:fstr | orderBy : '-price' | getRepeat">
        <td>{{obj.id}}</td>
        <td>{{obj.name}}</td>
        <td>{{obj.price | currency:"₩"}}</td>
        <td>{{obj.get}}</td>
    </tr>
    </table>
     
    </div>
</body>
</html>

이번에는 getRepeat 필터 외에 텍스트를 사용하여 검색하는 필터도 추가되어 있다. HTML 파일을 열면 “GET?“의 값이 true의 데이터만 테이블에 표시된다. 이것이 getRepeat 필터에 의한 처리이다.

표시를 확인한 후에 “검색"필드에 뭔가 텍스트를 입력해 본다. 그러면, 그 텍스트를 포함하는 항목만 표시된다. 이것은 filter 필터를 이용한 처리이다. filter를 사용하면 간단히 데이터를 검색할 수 있다.

<tr> 태그의 ng-repeat 부분을 살펴 보면, 이렇게 작성되어 있다.

ng-repeat="obj in ctl.data | filter:fstr | orderBy : '-price' | getRepeat"
  • obj in ctl.data : ctl.data의 배열 순서로 값을 꺼내 obj에 대입을 반복한다.
  • filter:fstr : 텍스트에 fstr 포함 여부 확인한다.
  • orderBy : ‘-price’ : price 값이 큰 순으로 정렬한다.
  • getRepeat : get 값이 true 것만 표시한다.

이런 식으로 4개의 값을 정리하고 있다. 첫번째 obj in ctl.data로 반복 처리를 하고, 그 3가지 리스트 필터로 배열의 내용을 조작하고 있다. 이것으로 “검색”, “정렬”, “getRepeat” 모두가 포함된다.

리스트 필터도 텍스트 필터와 같이 만들어 보면 의외로 쉽게 만들 수 있다. 리스트와 리스트 필터는 데이터의 표시를 하는 경우에는 필수 기능이라고 할 수 있다. 꼭 여기에 이해하도록 하자.