디렉티브(directive)는 템플릿에 삽입하여 사용하는 HTML적인 "태그"와 "속성"을 만드는 방법이다. 이를 제공함으로써 자신의 출력을 태그로 쉽게 표시할 수 있다. 디렉티브을 만들어, AngularJS를 파워업을 할 수 있다.


디렉티브 기본 및 생성

AngularJS에서는 HTML 태그에 고유한 속성을 추가하고, 혹은 태그를 작성하여 HTML안에 특수한 기능을 할당했다. 이러한 기능을 "지시어" 즉, 디렉티브(directive)라고 한다.

이 디렉티브은 AngularJS에 제공되어 있을 뿐만 아니라 직접 만들 수도 있다. 직접 디렉티브을 작성하여 자신만의 태그를 추가해 나갈 수 있는 것이다.

디렉티브은 모듈에 작성한다. 모듈의 객체에 제공하고 있는 "directive"라는 메소드를 이용하여 만든다. 이는 다음과 같은 형태로 작성한다.

모듈.directive(이름, 함수);

첫번째 인수는 디렉티브의 이름을 지정한다. 이 이름이 그대로 태그 이름과 속성 이름으로 사용할 수 있게된다. 두번째 인수에 디렉티브의 구체적인 처리를 하는 함수 객체를 지정한다.

directive 메소드 자체의 사용법은 간단한다. 문제는 인수에 제공하는 함수를 어떻게 만들면 되는가? 이다. 이는 "지시문에서 필요한 값을 가진 개체를 반환"처리를 생각합니다.

우선은 가장 간단한 형태로 "template"라는 값을 가진 객체를 반환하는 디렉티브 함수를 보도록 하자. 이는 다음과 같다.

function() {
    return {template: ... 출력 내용 ...};
}

"template"는 출력 태그의 템플릿이다. 즉, 여기에 준비한 내용이 그대로 Web 페이지에 표시된다고 할수 있다.

간단한 디렉티브 생성

간단한 예제를 만들어 보자. 여기에서는 "OK!"라고 출력하는 OK 디렉티브를 만들어 보겠다.

우선 다음과 같이 스크립트를 작성하고 "script.js"라고 저장한다.

var myapp = angular.module('myapp',[]);

myapp.directive('ok', function(){
    return {
        template:'<span style="font-size:24pt;color:red;">OK!</span>'
    };
});

여기에서는 directive의 첫번째 인자에 'ok'라고 지정하고 있다. 두번재 인수는 return {template : ...}와 같은 문장만을 수행하는 함수를 지정하고 있다. 디렉티브의 기본적인 구조를 안다면 그렇게 어려운 것을 하고 있는 것은 아니다라는 것을 알 것이다.

그럼, 이를 실제로 사용을 해보자. 아래에 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; }
    </style>
</head>
<body ng-app="myapp" ng-init="num=0">
    <h1>디렉티브</h1>
    <ok></ok>
</body>
</html>

이 Web 페이지를 열면, 빨간색으로 "OK!"가 표시된다.

리스트을 보면, <ok></ok>라는 태그가 작성되어 있고, 이것이 OK 디렉티브문을 이용하고 있는 부분이다. HTML은 <ok/>이라는 태그는 물론 없다. 이 <ok/> 태그가 아래와 같은 태그로 변환되는 것이다.

<span style = "font-size : 24pt; color : red;"> OK! </ span>

이러한 디렉티브를 사용하면, 간단한 커스텀 태그를 사용하여 복잡한 표시도 할 수 있다.



요소(element) 조작

아주 간단한 태그를 작성하는 디렉티브라면, 이것으로 충분히 사용할 수 있다. 그런데, 보통의 HTML 태그라는 것은, 그렇게 간단한 사용하는 것은 <br> 정도일 것이다. 보통은 시작 태그와 종료 태그 사이에 값을 쓰거나, 태그에 속성을 지정하여 좀 더 표현력을 갖게 된다.

디렉티브에서도 이런 일이 가능하다. 여기에는 directive 메소드의 인수로 제공하는 함수를 약간 수정해야 한다.

앞전 예제에서는 directive 메소드의 두번째 인수에서 지정한 함수에는 객체를 return하도록 하였다. 이런 방식이라면, 객체에 값을 준비하는 정도 밖에 할 수 없다. 이보다 복잡한 처리는 할 수 없다는 것이다.

그래서 return하는 값을 "함수 객체"로 하는 것이다. 그리고 이 함수에서 필요한 작업을 수행하도록 하면 된다. 이 경우에 함수는 다음과 같은 형태로 정의한다.

function() {
    return function(scope, element, attrs) {
        ...... 필요한 처리 ......
    });
}

return이 함수에는 3개의 인수가 준비되어 있다. 이들은 각각 다음과 같은 역할을 한다.

  • scope : 이것은 범위의 객체입니다.
  • element : 이 지시문의 DOM 요소입니다.
  • attrs : 속성 정보를 취급하는 객체이다.

디렉티브 태그에 있는 텍스트와 태그에 포함된 속성을 이용하려면 element와 attrs를 사용한다. 이러한 객체에서 필요한 정보를 얻어 조작하면 된다.

지시문 작성

그럼 앞에서 작성한 script.js의 디렉티브를 수정하고, 속성 및 태그에 포함된 텍스트를 이용하도록 변경해 보자.

아래에 그 예제를 올려 두었다.

var myapp = angular.module('myapp',[]);
 
myapp.directive('ok', function(){
    return function(scope,element,attrs){
        var size = attrs['size'];
        size = size == null ? '24pt' : size;
        var color = attrs['color'];
        color = color == null ? 'red' : color;
        var txt = element[0].textContent;
        var tag = '<span style="font-size:' + size  + ';color:' + color + ';">' + txt + '</span>';
        element[0].innerHTML = tag;
    };
});

여기에서는 "size", "color"라는 두 가지 속성과 태그에 적혀 있는 텍스트에 대응하는 처리를 하고 있다. 대략 정리하면 아래와 같다.

size와 color 속성

속성은 attrs 인수에 정리하고 있다. 여기에서는 이 attrs에서 size와 color 속성을 각각 변수에 얻을 수 있다.

var size = attrs['size'];
size = size == null ? '24pt' : size;
var color = attrs['color'];
color = color == null ? 'red' : color;

이 처럼 attrs[이름]라는 형태로, 지정된 이름의 속성 값을 얻을 수 있다. 그런데, 여기서 주의할 점은 "속성이 태그에 포함되지 않은 경우도 있다"는 것이다. 이 경우는 얻은 값은 undefined가 되기 때문에, 얻은 변수에 다시 값을 대입하도록 하여 대응해 두어야 한다.

태그의 값

예를 들어, <ok>Hello</ok>와 같이 태그에 값(여기에서는 Hello)를 작성하였을 때에, 이 값을 얻어 사용할 수 있다. 값은 다음과 같이 얻는다.

var txt = element[0].textContent;

인수로 전달되는 element가 디렉티브의 DOM 요소이다. 다만, 이것은 배열되어 있으며, 인덱스 번호 0 값이 첫번째 디렉티브의 DOM 요소가 된다(보통은 0번의 값 1개 밖에 없을 것이다).

element[0]에서 내부에 있는 값을 얻으려면, 여러가지 방법이 있을 것이다. 여기에서는 textContent로 이용하여 얻을 있다. 디렉티브 태그 또는 내부에 다른 태그가 내장되어 있거나 하면 이것으로는 처리할 수는 없지만, 단순히 내부에 텍스트가 작성되어 있다면 이것으로 충분하다.

element[0].innerHTML = tag;

그리고, 출력하는 태그를 텍스트로 작성하여 element[0].innerHTML에 그것을 대입한다. 이것으로 <ok> 태그의 내부가 교체된다.

디렉티브를 HTML에 통합

그럼 작성한 새로운 OK 디렉티브를 사용한다. 이용 예제를 아래에 올려 두었다.

<!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; }
    </style>
</head>
<body ng-app="myapp" ng-init="num=0">
    <h1>디렉티브</h1>
    <ok>This is sample!</ok>
    <hr>
    <ok size="36pt">This is size sample!</ok>
    <hr>
    <ok color="blue">This is color sample!</ok>
    <hr>
    <ok color="green" size="48pt">This is full sample!</ok>
</body>
</html>

여기에는 4개의 <ok> 태그를 작성하고 있다. 각각의 사용법은 아래와 같다.

· 특성 없음

<ok>This is sample!</ok>

· size 속성

<ok size="36pt">This is size sample!</ok>

· color 속성

<ok color="blue">This is color sample!</ok>

· size, color 속성

<ok color="green" size="48pt">This is full sample!</ok>

이처럼 size와 color 2가지 속성을 사용할 수 있다. 이러한 속성은 지정하지 않으면 각각 size="24pt"color="red"로 디폴트로 설정된다.

또한 모든 태그 안에 작성되어 있는 텍스트는 그대로 표시된다. 이것으로 텍스트의 색상과 크기를 간단히 설정할 수 있는 태그로써 <ok>를 만들 수 있게 되었다.



이벤트 설정

디렉티브는 표시를 커스터마이징하는 것만 할 수 있는 것은 아니다. 태그에 이벤트를 결합하여 움직이는 디렉티브를 만들 수 있다.

이것은 따로 특별한 테크닉이 필요한 것은 아니다. directive에서 전달되는 element 인수는 DOM 요소이기 때문에, 그대로 이벤트의 설정할 수 있다. onclick 속성 등에 함수를 대입하거나 또는 addEventListener 메소드를 호출하여 설정하면 된다.

간단한 예제를 아래에 올려 두었다.

var myapp = angular.module('myapp',[]);
 
myapp.directive('click', function(){
    return function(scope, element, attrs){
        element[0].addEventListener("click", function(){
            var txt = this.textContent;
            alert('you click "' + txt + '"!');
        }, false);
    };
});

이것은 클릭하면 alert를 표시하는 <click> 태그 디렉티브이다. 예를 들어, 아래와 같이 태그를 작성한다.

<click>This is click sample!</click>

이 텍스트 부분을 클릭하면 화면에 알림 창이 나타나 you click "This is click Sample!"!라는 메시지가 표시된다.

여기에서는 return하는 함수 객체 안에 다음과 같이 이벤트를 지정한다.

element[0].addEventListener("click", function(){
    ...... 클릭 처리 ......
}, false);

보통 이벤트 지정과 동일하다. 이것으로 디렉티브는 DOM 요소에도 보통으로 이벤트를 추가할 수 있다.



속성 디렉티브 생성

태그 자체를 통째로 디렉티브로 만들뿐 아니라 속성으로써 디렉티브을 만들 수 있다. 속성으로 지정하는 지시어는 다양한 HTML 태그 다음에 추가하여 사용할 수 있다는 장점이 있다.

이는 기본적인 작성법은 이전에 설명하였다. 객체를 return하는 방식과 동일하다. 다만, 지정하는 값이 조금 다를 뿐이다. 정리하면 이렇게 된다.

모듈.directive( 이름 , 
    function() {
        return {
        restrict: 'A',
        template: 출력 내용
        };
    });

directive에서 return하는 함수 객체에는 template 외에 "restrict"라는 값을 지정해 주고 있다. 이것은 그 디렉티브가 어디에 사용할 수 있는지를 나타내는 것으로, 다음과 같은 값을 사용할 수 있다.

  • 'E' : 요소로 사용할 수 있다. <ok>와 같은 형태이다.
  • 'A' : 속성으로 사용할 수 있다. <p ok>와 같은 형태이다.
  • 'AE' : 위 모두에서 사용할 수 있다.

restrict:'A'를 지정하면, 속성으로 사용할 디렉티브를 만들 수 있다는 것이다.

그럼 간단한 예제로 아래에 스크립트를 올려 두었다.

myapp.directive('ok', function(){
    return {
        restrict: 'A',
        template:function(scope, element){
            var size = 24;
            switch(element['ok']){
            case 'large':
                size = 48; break;
            case 'midium':
                size = 36; break;
            case 'small':
                size = 24; break;
            }
            var obj = scope[0];
            var tag ='<span style="font-size:' + size
                + 'pt">' + scope[0].textContent
                + '</span>';
            return tag;
        }
    };
});

이것은 ok 특성에 3개의 값을 작성되어 있다. 예를 들어, 이런 식으로 사용한다.

<div ok="large">This is Large sample!</div>
<div ok="midium">This is Midium sample!</div>
<div ok="small">This is Small sample!</div>

여기에서는 template 속성 값에 함수를 지정하고 있다. 복잡한 처리를 할 경우는 그렇게 하는 것이 편리하기 때문이다. 그러나 함수를 지정하는 경우에는 인수에 주의해야 한다.

template:function(scope, element){……});

이와 같이, scope와 element 2가지가 전달된다. 속성의 값은 element에서 직접 얻어 낼 수 있다. 여기에서는 element['ok']에서 ok 속성의 값을 얻고 있다.

또한, 이 ok 속성이 있는 태그 안에 작성되는 값은 scope[0].textContent로 얻어 오고 있다. element 가 아니고, scope에서 얻어 올 수 있기 때문에 주의가 필요하다.

속성 디렉티브는 어디까지나 주가 되는 태그에 추가하는 것이므로, 그 태그 자체를 과감하게 변경해 버리는 것이 아니라, 거기에 뭔가를 추가하는 정도의 것으로 설계하는 것이 좋다. 통째로 변경해 버리는 것은 요소로서 작성하는 것이 좋다.



'AngularJS' 카테고리의 다른 글

[AngularJS] 디렉티브(directive)  (0) 2017.12.27
[AngularJS] 리스트 필터  (0) 2017.12.26
[AngularJS] 필터  (0) 2017.12.26
[AngularJS] 모듈 및 컨트롤러  (0) 2017.12.26
[AngularJS] AngularJS 기본  (0) 2017.12.26

많은 데이터를 반복해서 표시하는데 할 때 유용한 것이 "리스트(list)"이고, 이 리스트의 항목을 나중에 조작할 수 있는 것이 "리스트 필터"이다. 이 두 가지를 결합하여 데이터 나열하는 방법에 대해 설명한다.


리스트 반복 처리

데이터를 취급하는 Web 페이지의 경우, 같은 형식의 다량의 데이터를 테이블 등의 형태로 표시하는 경우가 많다.

이런 경우는 어떤 "같은 표시를 반복 실행한다"라는 구조를 갖고 있다. 즉, 데이터를 "이런 형태로 작성해 간다"라는 것만 지정하면 이후에는 데이터를 전달하면 그 하나 하나를 반복하는 같은 형식으로 출력해 주는 구조이다.

AngularJS에는 "리스트"이라는 것이 있다. 이것은 배열 등의 형태로 정리한 것 중에서 순서대로 값을 꺼내 처리해 가는 구조이다. 이것은 HTML에 속성을 추가하는 것만으로 간단하게 사용할 수 있다.

그러면 예제을 만들면서 설명해 보겠다. 우선 스크립트를 작성하여, "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:false},
            {id:3,name:'windows phone',price:38765,get:true}
        ];
    }
);

여기에서는 HeloController라는 컨트롤러(이전까지 사용했던 예제)에 "data"라는 변수에 id, name, price, get 같은 항목의 데이터를 배열로 정리되어 있다. 이 데이터를 목록으로 형태 표시하려고 한다.

ng-repeat 동작

다음으로는 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>
    <div ng-controller="HeloController as ctl">

    <table>
    <tr><th>ID</th><th>NAME</th><th>PRICE</th><th>GET?</th></tr>
    <tr ng-repeat="obj in ctl.data">
        <td>{{obj.id}}</td>
        <td>{{obj.name}}</td>
        <td>{{obj.price | currency:"₩"}}</td>
        <td>{{obj.get}}</td>
    </tr>
    </table>
     
    </div>
</body>
</html>

이렇게 작성하여 브라우저에 표시해 본다. data의 데이터가 테이블로 표시된다.

여기에서는 테이블을 사용하여 데이터를 표시하고 있다. 이 부분이다.

<table >
  <tr><th>……생략……</th></tr>
  <tr ng-repeat="obj in ctl.data">
    <td>{{obj.id}}</td>
    <td>{{obj.name}}</td>
    <td>{{obj.price | currency:"₩"}}</td>
    <td>{{obj.get }}</td>
  </tr>
</table>

<table>에는 특별한 것은 없다. 태크안에는 <tr> 태그에 있다. 여기에서 리스트에 의한 반복의 속성 (디렉티브)가 작성되어 있다. 이것은 다음과 같이 작성한다.

ng-repeat="변수 in 배열"

이 ng-repeat는 준비되어 있는 배열에서 값을 꺼내 변수로 설정하고, 이 ng-repeat가 적혀있는 태그를 출력한다. 즉, 배열에 저장되어 있는 값의 수만큼 ng-repeat가 작성되어 있는 태그가 반복 출력된다. <tr> 태그 내에 <td> 태그를 보면,

<td>{{obj.id}}</ td>

이와 같이, 배열에서 얻는 변수 obj 객체의 속성을 지정하여 출력시키고 있다. 객체를 배열에 정리해두면, 이런 식으로 객체 내에 값도 자유롭게 다룰 수 있다.


리스트 필터

여러 데이터를 반복 표시하는 것은 리스트에서 간단히 할 수 있는 것을 알 수 있었다. 이 리스트는 단순히 배열의 내용을 순서대로 표시만 할 수 있는 것은 아니다. 표시할 때에 여러가지 데이터를 조작할 수 있다.

예를 들어, 앞전에 예제에서 <tr> 태그 부분을 다음과 같이 바꾸어 본다.

<tr ng-repeat = "obj in ctl.data
    | orderBy : '-price' ">

이렇게 하면 데이터의 price 값이 큰 것부터 순서대로 정렬하여 표시한다.

여기에서는 obj in ctl.data 다음에 | 기호를 붙이고, 거기에 orderBy : '-price'라는 것이 설정하였다. 이것은 목록에 적용할 필터인 "리스트 필터"이다. 먼저 텍스트를 표시할 때 사용하는 "필터"에 대해 설명했는데, 리스트 필터는 그것에 리스트 버전이라고 할 수 있다. 리스트에 표시되는 항목과 순서 등을 조작 할 수 있는 것이다.

그럼 반복 표시에 사용할 수 있는 필터에 대해 설명한다.

정렬 순서 지정

orderBy : 항목 이름

앞에 예제에서 사용한 것이다. 이것은 지정된 항목을 사용하여 배열을 정렬한다. 콜론 뒤에 항목 이름을 지정한다. 이 때, 이름 앞에 마이너스 기호(-)를 붙이면 역순으로 정렬한다. 예를 들어, price라고 지정하면 price가 작은 것부터 순서대로 되지만 -price라고 큰 순서로 나열된다.

최대 항목 수를 지정

limitTo: 정수

배열의 항목 수를 지정한다. 예를 들어, limitTo:5라고 지정하면 앞에서 5개를 꺼낸다. 또한 limitTo:-5와 같이 마이너스 기호를 붙여서 지정하면, 마지막 5개를 꺼낼 수 있다.

값 비교

filter: 패턴

정규식 패턴을 사용하여 특정 항목만을 추출하는데 사용하는 것이다. 이것은 텍스트 필터도 사용 했었다. 리스트의 경우는 리스트의 항목이 패턴과 일치하는 것만을 꺼내어 처리할 수 있다. 예를 들어, filter:'ok'라고 지정하면 값이 'ok'항목만 표시된다.



커스텀 리스트 필터

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

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

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

컨트롤러.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" 모두가 포함된다.

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



'AngularJS' 카테고리의 다른 글

[AngularJS] 디렉티브(directive)  (0) 2017.12.27
[AngularJS] 리스트 필터  (0) 2017.12.26
[AngularJS] 필터  (0) 2017.12.26
[AngularJS] 모듈 및 컨트롤러  (0) 2017.12.26
[AngularJS] AngularJS 기본  (0) 2017.12.26

AngularJS에는 "필터"라는 기능을 사용하여 값의 표시를 조작할 수 있다. 이 필터의 사용법에 대해 설명한다.


필터란?

AngularJS에는 {{}}라는 태그를 사용하여, 다양한 값을 표시할 수 있다. 단순히 값을 표시할 뿐이라면 대부분 프로그래밍이 아니었다. 그러나 값이라는 것은 단순히 "전달된 것을 그대로 표시할 뿐"이라는 것만은 아니다.

예를 들어, 숫자 값을 금액으로 ₩ 기호를 표시하려고 한다고 하자. 이 경우 모든 출력 부분에 ₩ 기호를 추가해 간다는 것은 그렇게 쉽다고 할 수 없다.

이런 경우에 이용되는 것이 "필터"이다. 필터는 다양한 값을 자동으로 조작할 수 있는 기능이다. 이것은 다음과 같이 사용한다.

{{변수 | 필터}}

변수의 후에 | 기호를 붙이고 그 다음에 필터를 제공한다. 여러 필터를 동시에 사용하려면,

{{변수 | 필터1 | 필터2 | ...}}

이렇게 하면 몇개도 연결해 쓸 수 있다.

이 필터는 AngularJS 자체에 일반적인 것이 몇 가지가 제공되며, 언제든지 사용할 수 있다. 또한 자신의 필터를 프로그램화하여 사용할 수도 있다.

모듈 및 컨트롤러 생성

필터를 이용한 예제를 만들어 보자. 먼저 프로그램부터 작성한다.

아래 프로그램의 간단한 예제 코드를 올려 두었다. 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,date:1450100000000},
            {id:1,name:'Android phone',price:7800,get:true,date:1450400000000},
            {id:2,name:'New iPhone',price:549020,get:false,date:1450200000000},
            {id:3,name:'windows phone',price:38765,get:true,date:1450300000000}
        ];
        this.getData = function(){
            return this.data[this.count].id + ': ' + 
                this.data[this.count].name + ', ' + 
                this.data[this.count].price + '.' +
                this.data[this.count].date;
        };
    }
);

이번에는 HeloController 클래스에 count, data, getData 라는 속성과 메소드를 정의하고 있다. data는 매우 간단한 카탈로그 같은 것을 나타낸다. ID, 이름, 가격 그리고 가지고 있는지에 대한 여부를 나타내는 부울값, 등록 일시 등의 정보가 있다. 등록 일시는 타임 스탬프의 정수값으로 지정되어 있다.

이 data의 데이터를 템플릿으로 표시할 때에 필터를 이용하기로 한다.

값을 필터링

필터를 사용하여 데이터를 표시시켜 본다. 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>
    <div ng-controller="HeloController as ctl">
     
    <table>
    <tr><th>ID</th><th>NAME</th><th>PRICE</th><th>GET?</th><th>DATE</th></tr>
    <tr ng-repeat="obj in ctl.data">
        <td>{{obj.id}}</td>
        <td>{{obj.name}}</td>
        <td>{{obj.price | currency:'₩'}}</td>
        <td>{{obj.get}}</td>
        <td>{{obj.date | date:'yyyy-MM-dd'}}</td>
    </tr>
    </table>
     
    </div>
</body>
</html>

이와 같이 소스 코드를 다시 브라우저에 표시하려고 한다.

이번에는 PRICE 및 DATE 항목에 필터를 설정하여 두었습니다. 각각의 출력을 하고 있는 부분을 살펴 보자.

PRICE 출력

{{obj.price | currency : '₩'}}

obj.price 다음에 "currency"라는 필터를 설정하고 있다. 이것은 숫자를 금액으로 포맷하여 표시하는 필터이다. 필터에 따라 필요한 값을 준비하는 것이 있다. 이 currency도 그중 하나로 '₩'으로 지정하여 원형 표기에 설정할 수 있다. 출력된 표시를 보면 "₩ 7,800.00"라는 형식으로 표시되는 것을 확인할 수 있을 것이다.

DATE 출력

{{obj.date | date : 'yyyy-MM-dd'}}

obj.date 다음에 "date"라는 필터가 설정되어 있다. 이것은 Date 객체의 값을 특정 형식으로 포맷하는 필터이다. 여기에서는 'yyyy-MM-dd'로 설정하고 있다. 이것으로 예를 들어 "2015-12-14"라는 형식으로 날짜가 표시된다.

그런데 date 값은 타임 스탬프 정수였다. date 필터를 이용하면 타임 스탬프를 바탕으로 Date 객체를 생성하고 그것을 바탕으로 지정된 형식으로 포맷된 텍스트를 얻을 수 있다.

이와 같이 필터를 사용하면 단순한 수치가 금액 표기하거나 날짜를 표시할 수도 있다.



표준 필터

필터는 매우 쉽게 사용할 수 있지만, 도대체 어떤 필터가 준비되어 있는지 모르면 사용 방법할 수 없다. 여기에서 AngularJS에 표준으로 제공되는 필터에 대해 설명한다.

currency

숫자를 금액으로 표기하기 위한 필터이다. 단순히 currency만 지정하면 달러 표기로 표시된다. currency : '₩' 이렇게 하면 원화가 표시된다.

date

Date 값을 정해진 형식의 날짜 텍스트에 서식하는 필터이다. 포맷의 이름이나 어떤 패턴을 값으로 지정한다. 포맷의 이름과 패턴에서 사용할 수 있는 메타 문자는 다음과 같다.

포맷 이름

포멧 이름설명
short, shortTime, shortDate짧은 형식의 포맷이다.
medium, mediumTime, mediumDate통상적으로 사용되는 형식의 포맷이다.
longDate, fullDate긴 형식의 날짜 포맷이다.

패턴의 메타 문자

문자설명
y년 (서기)를 나타낸다.
M월을 나타낸다.
d일을 나타낸다.
E요일을 나타낸다.
H24시간제의 시간을 나타낸다.
h12시간제의 시간을 나타낸다.
m분을 나타낸다.
s초를 나타낸다.
.sss밀리 초를 나타낸다.
a오전, 오후를 나타낸다.
z타임존을 나타낸다.

number

숫자를 특정 자릿수로 반올림하여 표시하는 필터이다. 예를 들어, number : 4라고 하면 앞에 4자리만 표시하고 5번째 자리를 반올림한다.

json

객체의 값을 JSON 형식으로 변환하여 출력하는 필터이다.

uppercase / lowercase

텍스트를 모두 대문자 또는 소문자로 변환하는 필터이다.



커스텀 필터

필터는 기본적으로 제공되는 것뿐만 아니라 사용자가 직접 필터를 만들 수 있다. 이 커스텀(사용자 정의) 필터는 다음과 같은 형태로 정의된다.

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

컨트롤러 filter 메소드를 사용하여 필터를 등록한다. 인수에는 필터 이름과 필터 처리를 구현한 함수가 필요하다.

인수에 설정되는 함수는 대체로 다음과 같은 형태로 정의해야 한다.

function(val) {
    ...... 중략 ......
    return 값;
}

인수로 전달되는 것이 필터에 걸린 원래 값이다. 그리고 return하는 것이 필터링된 값이다. 즉, 함수에서 인수 값을 어떻게 변환하여 return할지 생각하면서 코딩하면 필터는 비교적 쉽게 만들 수 있다.

getIt 필터

그럼 간단한 예제를 만들어 보자. 컨트롤러에 준비되어 있는 data에 구입 여부를 부울값으로 나타내는 "get"값이 있었다. 이것을 좀 더 알기 쉽게 표시하는 필터를 생각해 보다.

아래에 예제을 올려 두었다.

helo.filter('getIt', 
    function(){
        return function(val) {
            return val ? "✔" : "-";
        };
    }
);

이를 script.js 끝에 추가한다. 그리고 HTML 파일의 get을 표시하고 있는 부분인 {{obj.get}} 여기에 다음과 같이 수정한다.

<td>{{obj.get | getIt}}</td>

이렇게 get에 필터를 넣으면 "✔"가 표시되는 것을 확인할 수 있다. 여기에서 val의 값에 따라 "✔"또는 "-"중 하나를 return하도록 되어 있는데, true라면 "✔", false이면 "-"로 표시되게 된다.

필터에 값을 설정

필터에는 currency나 date처럼 어떤 값을 설정하고 호출 할 수도 있다. 여기서 그 방법을 설명한다.

이는 간단합니다. 필터 함수를 정의할 때, 두번째 인수를 지정하여 값을 전달할 수 있다.

앞에서 만든 필터 getIt을 수정하여 값을 전달할 수 있도록 해보자. 아래에 간단한 예제를 올려두었다.

helo.filter('getIt', 
    function(){
        return function(val,opt) {
            var t = (opt == null) ? '✔' : opt;
            return val ? t : '-';
        };
    }
);

두번째 인수 opt의 값이 null 없는지 확인하고, null가 아닌 경우는 true시에 return하도록 수정되었다. null의 경우는 "✔"를 return한다.

그러고 HTML 파일의 obj.get을 출력하고 있는 부분에 다음과 같이 수정한다.

<td>{{obj.get | getIt:'●'}}</td>

이것으로 값이 true라고 "●", false이면 "-"로 표시되도록 되었다. getit : '●'와 같이 준비한 값이 그대로 true의 표시가 되는 것이다. 또 다른 값을 변경하여 표시가 잘되는지 확인해 본다.

 

필터는 인수에 어떻게 return 값을 생성되는지 알면 의외로 간단히 만들 수 있다. 또한 만든 필터를 이용하는 것도 매우 간단하다. 용도에 따라 자신만의 필터를 만들 수 있게 되면, 표현력도 훨씬 좋아진다.



'AngularJS' 카테고리의 다른 글

[AngularJS] 디렉티브(directive)  (0) 2017.12.27
[AngularJS] 리스트 필터  (0) 2017.12.26
[AngularJS] 필터  (0) 2017.12.26
[AngularJS] 모듈 및 컨트롤러  (0) 2017.12.26
[AngularJS] AngularJS 기본  (0) 2017.12.26

AngularJS에는 "모듈"이라는 객체를 만들어, 그 안에 '컨트롤러'라고 것을 만든다. AngularJS 이용의 가장 기본이 되는 이 두 개체의 생성 및 이용에 대해 설명한다.


모듈 및 컨트롤러 정의

앞에서는 AngularJS를 사용했지만 이전 예제에는 JavaScript 스크립트가 없었다. 역시 본격적인 처리를 구현하려고 되면 "스크립트를 어떻게 조합하는지"가 중요하다.

모듈

AngularJS에는 "모듈"이라는 것을 사용하여 스크립트를 결합한다. 모듈이라는 것은 AngularJS에서 사용되는 "프로그램의 모음" 같은 것이다. AngularJS에는 프로그램은 모듈 단위로 결합한다. 모듈 안에는 몇 개의 작은 프로그램을 결합해 둘 수 있다.

AngularJS에는 ng-app라는 속성을 지정하여, 해당 태그에 AngularJS의 기능을 할당할 수 있었다. 이 ng-app를 사용하면, 모듈 이름을 지정할 수 있도록 되어 있다. 예를 들어,

<body ng-app="hoge">

이런 식으로 하면, 이 <body> 태그에 hoge 모듈의 기능을 사용할 수 있게 된다.

컨트롤러

모듈은 프로그램이 정리된 것이지만, 그 자체로 직접 뭔가 처리가 포함되는 것은 아니다. 일반적으로 이 모듈에 "컨트롤러(controller)"라는 것을 만든다.

컨트롤러는 다양한 작업 및 값을 정리한 객체이다. 이 컨트롤러에 메소드와 속성을 만들어 가는 것이 "AngularJS의 프로그램 작성"하는 거라고 할 수 있다. 모듈에 이 컨트롤러를 필요한 만큼 얼마든지 보관할 수 있다.

컨트롤러의 이용도 모듈과 같이 태그에 컨트롤러 지정을 작성한다. 이것은 ng-controller라는 속성을 사용한다.

<○○ ng-controller="컨트롤러 이름">

이것으로 이 <○○> 태그 내부에 지정한 컨트롤러를 사용할 수 있다. 모듈에는 여러 컨트롤러도 둘 수 있으므로, 필요에 따라 "이 부분에서는 A 컨트롤러"와 같이 사용 범위를 바꾸면서 사용할 수 있다. 물론 여러 컨트롤러를 동시에 사용할 수도 있다.

모듈 및 컨트롤러. 이 두 가지가 무엇인지를 이해하는 것이 AngularJS 개발의 첫 걸음이다.



모듈 및 컨트롤러 생성 및 사용

모듈 및 컨트롤러에 대한 간단한 예제를 만들어 사용하는 방법에 대해 설명한다.

우선은 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; }
    </style>
</head>
<body ng-app="myapp" ng-init="num = 1000">
    <h1>세금 계산</h1>
    <p>금액을 입력하십시오.</p>
    <div ng-controller="HeloController as ctl">
    <div class="input">
        <span class="label">tax:</span>
        <input type="text" ng-model="ctl.tax"></div>
    <div class="input">
        <span class="label">price:</span>
        <input type="text" ng-model="num"></div>
    <p class="msg">세금 포함 : {{ctl.calcWithTax(num)}}원</p>
    <p class="msg">부가세 제외 : {{ctl.calcWithoutTax(num)}}원</p>
    </div>
</body>
</html>

여기에서는 <script src="script.js"></script>라는 형태로 스크립트 파일을 로드하고 있다. 이 script.js라는 파일이 AngularJS의 본체 프로그램이다.

일반적으로 JavaScript 프로그램이라는 것은 HTML 파일에 직접 삽입하여 작성하거나, 별도의 스크립트 파일을 만들어 그것을 로드하여 가져온다. AngularJS에도 어떤 방식으로도 프로그램을 만들 수 있다.

하지만 MVC 아키텍처를 중시하고 화면 표시와 처리의 분리를 생각한다면, HTML 안에서 그대로 JavaScript 코드를 작성하는 것은 그다지 좋은 방법은 아닐 것이다. 여기처럼 다른 파일로 구분하여 거기에 컨트롤러를 작성하는 것이 자연스럽다.

컨트롤러 사용

여기에서는 먼저 다음과 같이하고 "myapp"라는 모듈을 이용하고 있다.

<body ng-app="myapp" ng-init="num = 1000">

이렇게 하여 myapp 모듈에 있는 컨트롤러를 사용할 수 있다. 여기에서는 다음과 같이 컨트롤러를 이용하고 있다.

<div ng-controller="HeloController as ctl">

myapp 모듈에는 "HeloController"라는 컨트롤러를 준비되어 있다. 그런데 이는 조금 이름이 너무 길다. "as"은 컨트롤러에 별칭(alias)으로 줄 수 있다. 여기서 지정한 HeloController as ctl라고 하면 "ctl"라는 이름으로 HeloController을 사용할 수 있게 된다.

<input type="text" ng-model="ctl.tax"><input type="text" ng-model="num">

입력 필드의 <input> 태그에는 ng-model으로 모델을 지정한다. num은 <body> 태그에 ng-init="num = 1000"라는 형태로 초기화되어 있는 값이다.

ctl.tax는 컨트롤러에 있는 값이다. `ctl(HeloController) 안에 있는 "tax"라는 속성을 모델로 설정되어 있는 것이다.

<p class="msg">세금 : {{ctl.calcWithTax(num)}}원</p>
<p class="msg">부가세 제외 : {{ctl.calcWithoutTax(num)}}원</p>

이후 이와 같이 작성되어 있다. 이것은 각각 HeloController에 있는 "calcWithTax", "calcWithoutTax '라는 메소드 값을 작성한 것이다. 컨트롤러에 있는 처리(메소드)는 이런 식으로 호출할 수 있다.

스크립트 생성

이번에는 예제에서 사용하는 스크립트를 작성한다. 아래에 그 예제 코드를 올려 두었다. "script.js"라는 파일 이름으로 HTML 파일과 같은 위치에 배치한다.

angular.module('myapp',[])
    .controller('HeloController',
        function(){
            this.tax = 8;
             
            this.calcWithTax = function(val){
                return Math.floor(val * (100 + this.tax * 1) / 100);
            };
             
            this.calcWithoutTax = function(val){
                return Math.floor(val / (100 + this.tax * 1) * 100);
            };
        }
    );

이번 예제는 앞전에 만든 소비세 계산을 수정한 것다. tax과 price라는 두 개의 입력 필드가 있었다. 여기에 각각 세율(%) 및 금액을 기입하면 실시간으로 그 세금 포함 가격과 세금 가격을 계산하여 표시하는 연산이 여기에 포함되어 있다.

모듈 생성

angular.module(이름, 배열);

모듈의 작성은 angular 라는 객체의 module 메소드를 사용해 실행한다. angular라는 객체는 AngularJS의 기본이 되는 객체이다. AngularJS의 기능은 모든 이 angular 객체에 정리되어 있다.

module 메서드는 첫번째 인수에 모듈 이름의 텍스트를 지정한다. 두번째 인수에는 이 모듈이 참조하는 다른 모듈을 배열에 정리해 지정한다. 특별히 참조하는 것이 없다면 빈 배열로 둔다.

또한, 여기에서는 특별히 사용하지 않았지만, module 메소드는 생성된 모듈 객체를 반환 값으로 반환한다.

컨트롤러 생성

모듈.controller(이름, 함수);

컨트롤러는 module에서 만든 모듈에 있는 "controller"메소드로 작성한다. 첫번째 인수는 컨트롤러의 이름을 지정한다.

두번째 인수가 문제이다. 여기에 컨트롤러에 결합 구현 부분이 포함된다. "함수"라고 되어 있는데, 이것은 컨트롤러의 "생성자 함수"가 된다.

생성자 함수라는 것은 JavaScript에서 객체를 생성하는데 이용되는 것이다. 여기서 속성과 메소드를 정의하면 된다.

모듈 형태

이번에는 앞에서 작성한 예제 코드를 살펴 보자. 이번 샘플은 다음과 같은 형태로 되어 있다.

angular.module('myapp',[])
    .controller('HeloController',
        function() {
            ……중략……
        }
    }
);

angular.module에는 모듈 myapp를 만들고, controller를 호출하여 HeloController을 정의하고 있다. 생성자 함수 내에는 tax 속성과 calcWithTax, calcWithoutTax의 두 가지 메소드르 제공하고 있다.

이런 식으로 "모듈 생성", "컨트롤러 생성", "생성자 함수에서 필요한 값과 처리 구현"하는 것이 모듈 및 컨트롤러 사용의 기본이다.

생성자 함수

컨트롤러에 준비되어 있는 "생성자 함수"를 어떻게 만들지가 AngularJS 이용의 핵심이다.

생성자 함수는 JavaScript의 객체를 생성하는 함수이다. 이것은 객체에 제공하는 속성과 메소드를 내부에서 정의해야 한다.

function(){
    this.○○ = ☓☓; // 속성 정의
    this.△△ = function(){……} // 메소드 정의
}

생성자는 속성과 메소드(알기 쉽게 말하면, 값을 저장 변수로 처리를 구현하는 함수)를 그 내부에서 정의한다. 이것은 "this. ○○"와 같이 this 내에 속성에 대입하는 형태로 작성한다.

this는 생성자 함수에 의해 생성되는 객체 자신이다. 이렇게 하여 객체 자체의 속성에 값을 할당하여 객체의 내용을 만들어 간다. 생성자 함수는 AngularJS에 한정되지 않고, JavaScript 전반에서 사용되는 기술이다.



간단한 데이터베이스 생성


'AngularJS' 카테고리의 다른 글

[AngularJS] 디렉티브(directive)  (0) 2017.12.27
[AngularJS] 리스트 필터  (0) 2017.12.26
[AngularJS] 필터  (0) 2017.12.26
[AngularJS] 모듈 및 컨트롤러  (0) 2017.12.26
[AngularJS] AngularJS 기본  (0) 2017.12.26

AngularJS는 지금까지의 JavaScript 라이브러리과는 다른 새로운 형태의 사용법을 제공한다. 그 기본적인 구조 및 기능에 대해 설명한다.


AngularJS 란?

여기에서는 AngularJS를 사용하여 간단한 예제를 만들어 보겠다.

일단은 설치 및 개발 환경은 필요 없다. JavaScript를 편집 할 수 있는 적당한 편집기를 사용한다. 작업 서버의 준비도 우선 없어도 된다. HTML 파일을 그대로 브라우저에서 열어도 동작한다. Ajax 이용으로 서버 액세스 필요하게 되면 그 때 생각하면 된다.

그럼 아래에 간단한 예제 코드를 올려 두었다. 텍스트 에디터를 열어서, 작성해서 .html 확장자로 적당한 위치에 저장한다.

<!DOCTYPE html>
<html ng-app>
<head>
    <title>AngularJS Sample</title>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
</head>
<body>
    <div>
    <p>input:<input type="text" ng-model="msg"></p>
    <p>you typed: {{msg}}.</p>
    </div>
</body>
</html>

그리고 브라우저에서 열어본다.

이 예제에서는 입력 필드가 하나만 제공되고 있다. 여기에 텍스트를 입력하면 실시간으로 아래의 메시지에 표시가 된다. 아주 간단한 것이지만, AngularJS의 동작은 어떻게든 알 수 있을 것이다.

AngularJS을 사용하고 있다고 하는데 보면 알 수 있듯이 JavaScript 코드 같은 것은 전혀 없다. 사실 AngularJS의 큰 장점은 "JavaScript 만 확장하는 것은 아니다"라는 점이다. AngularJS는 HTML 자체를 확장한다. 그럼 어떻게 되어 있는지 자세히 살펴 보도록 하자.

AngularJS 로드

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>

AngularJS는 일반적으로 Google에서 로드하여 사용한다. 위와 같이 <script> 태그를 사용하여 다른 AngularJS를 사용할 수 있다.

이 ajax.googleapis.com라는 사이트는 Google에서 제공하는 CDN 사이트이다. CDN은 "Code Delivery Network"의 약자로 널리 사용되고 있는 오픈 소스 JavaScript 코드를 배포하는 사이트이다. jQuery와 Prototype과 같은 주요 오픈 소스 JavaScript 라이브러리는 대부분 여기에서 배포되고 있다. 지정된 라이브러리의 주소를 src에 지정하기 만하면 언제든지 라이브러리를 사용할 수 있게 된다.

모델 및 마크업

앞에 예제에서 텍스트를 작성하고 실시간으로 표시가 업데이트되는 것은 "모델"과 "마크업"이라는 것의 작용에 의한 것이다. 그럼 예제에서 사용되고 있는 AngularJS의 기능에 대해 설명하겠다.

응용 프로그램 지정

<html ng-app>

먼저 <html> 태그에 ng-app라는 것이 지정되어 있다. 이것은 "이 태그의 내부가 AngularJS에 의해 동적으로 연결된다"라는 것을 의미하고, app는 응용 프로그램을 의미한다.쉽게 말하면, "이 태그가 AngularJS 애플리케이션이다"라는 것을 의미하는 것이다.

여기에서는 <html> 태그에 지정하였는데, 이것은 HTML 전체를 AngularJS 연결하는 대상으로 하고 있기 때문이다. <body>로 연결되면 그 안에만 대상이 된다. 혹은 더 나중에 설명하겠지만, ng-app는 이름을 붙여서 여러 설정할 수 있기에 <body> 안의 여러 태그에 다른 이름의 ng-app을 지정할 수도 있다.

아무튼, 지금은 "<html>이나 <body>에 ng-app를 지정해 놓으면 AngularJS를 사용할 수 있게 된다"라는 것만 기억하도록 한다.

모델의 설정

<input type="text" ng-model="msg">

페이지 본문에 나오는 첫번째 핵심은 이 부분이다. "ng-model"라는 것이 지정되어 있다. 이것은 "디렉티브(directive)"라는 것이다. 디렉티브는 AngularJS에 의해 새롭게 추가된 태그의 속성이라고 생각하면 된다.

이 ng-model이라는 디렉티브는 "모델"이라는 것을 설정한다. 모델은 Web 페이지에 표시되는 데이터를 나타내기 위한 것이다. 예를 들어, 여기에 지정된 ng-model="msg"은 <input type="text"> 값이 "msg"라는 모델과 연관된 것임을 나타낸다.

마크업 사용

이 모델의 값은 여러 곳에서 사용할 수 있다. 여기에서는 그 다음와 같은 형태로 작성되어 있다.

<p>you typed: {{msg}}.</p>

이 {{OO}}라고 작성 법은 AngularJS에 의해 새롭게 마련된 마크업(markup)이다. 이 마크업은 수식이나 값을 HTML에 넣기 위하여 이용한다. 여기에서는 {{msg}}라고 되어 있는데, 이는 msg 값이 여기에 표시되게 된다.

이 모델과 마크업에 의해 모델에 설정된 필드의 값을 입력하여 변경이 되면, 마크업 표시가 즉시 바뀌는 동작을 한다. 이 두 가지 요소는 AngularJS를 사용할 때의 가장 기초적인 것이므로, 꼭 기억해 두기로 한다.


초기화와 계산 및 실시간 조작

여기서는 좀 더 확장하여 좀 쓸만한 것을 만들어 보자.

초기화와 계산

아래에 소비세의 계산을 하는 예제이다.

<!DOCTYPE html>
<html ng-app>
<head>
    <title>AngularJS Sample</title>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
</head>
<body ng-init="num = 100">
    <div>
    <p>price:<input type="text" ng-model="num"></p>
    <p style="font-weight:{{(num >= 10000) * 700}}">
        you typed: {{num * 1.08}}.</p>
    </div>
</body>
</html>

필드에 금액을 입력하면 세금(8% 세금)의 금액이 아래에 표시된다. 또한 금액이 1만원 이상이 되면, 금액 표시가 굵게 표시된다.

■ 초기화 처리

이번에는 새로운 디렉티브 하나가 추가되어 있다. 그것은 아래와 같다.

<body ng-init="num = 100">

이 ng-init라는 디렉티브는 모델의 초기화를 위한 것이다. 이것을 지정해 두면, 모델 값이 지정된 값으로 초기화된다.

■ 수식 사용

값을 표시하는 마크업 부분도 조금 바뀌었다. 이번에는 아래 같은 수식으로 값을 표시하고 있다.

you typed: {{num * 1.08}}.

이렇게 마크업에 수식을 설정할 수 있다. 이것으로 계산 결과가 자동으로 표시되도록 한다. 간단하다.

수식을 사용한 마크업은 잘 보면 다른 곳이 있다. 결과를 표시하고 있는 <p> 태그 부분이다.

<p style="font-weight:{{(num >= 10000) * 700}}">

num> 10000는 num의 값이 10000 이상이면 true, 미만이면 false가 된다. 이에 700을 곱하면 부울 값 (true 또는 false)은 정수 값(1 또는 0)에 캐스팅되어 1 * 700 또는 0 * 700이다. 그럼 "10000 이상이면 굵게 표시"가 되는 것이다.

단순히 간단한 계산만 하여도 이런 식으로 재미있는 것이 가능하다.

위치와 크기를 실시간 조작

그럼 모델과 마크업의 이용 예제로 표시되는 DOM의 위치나 크기를 실시간으로 조작하는 예제을 만들어 본다.

아래에 예제를 올려 두었다.

<!DOCTYPE html>
<html ng-app>
<head>
    <title>AngularJS Sample</title>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
    <style>
    #rect {
        background-color:red;
        position:absolute;
    }
    </style>
</head>
<body ng-init="x = 100;y = 100; w = 100;h = 100">
    <div>
    x:<input type="number" min="0" max="300" ng-model="x" size="5">
    y:<input type="number" min="0" max="300" ng-model="y" size="5">
    w:<input type="number" min="0" max="300" ng-model="w" size="5">
    h:<input type="number" min="0" max="300" ng-model="h" size="5">
    </div>
    <div id="rect" style="left:{{x}}px;top:{{y}}px;width:{{w}}px;height:{{h}}px">
    </div>
</body>
</html>

4개의 필드의 값을 조작하여 변경하면, 실시간으로 빨강 사각형의 위치와 크기가 달라진다.

여기에서는 먼저 <body> 부분에서 값의 초기화를 하고 있다.

<body ng-init="x = 100;y = 100; w = 100;h = 100">

여러 값을 초기화를 하려면, 이런 식으로 세미콜론(;)으로 구분하여 작성할 수 있다. 즉, JavaScript 코드를 작성할 뿐이다.

<input type="number">에 ng-model을 정의하는 것은 이미 알고 있을 것이다. 이는 각각의 입력된 값이 x, y, w, h라는 것에 보관된다. 그리고 이러한 값을 원래 사각형의 <div> 표시가 설정된다.

<div id="rect" style="left:{{x}}px;top:{{y}}px;width:{{w}}px;height:{{h}}px">

{{}}에 의해 마크업은 이런 방식으로 style 속성 값에 넣을 수 있다. 마크업은 HTML 어디서나 쓸 수 있다. 그리고 그 값을 조작할 수 있다.

어떤가? 아직 JavaScript 코드는 거의 작성하지 않았는데(변수 초기화만 작성), 그래도 여러가지 재미있는 것을 할 수 있을 같지 않은가? 모델과 마크업을 사용하여 실제로 HTML의 다양한 값을 조작해 보도록 하자.



'AngularJS' 카테고리의 다른 글

[AngularJS] 디렉티브(directive)  (0) 2017.12.27
[AngularJS] 리스트 필터  (0) 2017.12.26
[AngularJS] 필터  (0) 2017.12.26
[AngularJS] 모듈 및 컨트롤러  (0) 2017.12.26
[AngularJS] AngularJS 기본  (0) 2017.12.26

+ Recent posts