본문 바로가기

Javascript/Angular

avaScript Data Binding with AngularJS Part II – Binding a View to a Controller/ViewModel


위의 글을 번역한 겁니다. 다소 내용이 변경될수 있습니다.

나의 전 post에서 데이터바인딩을 할때 AngularJS프레임워크가 어떻게 사용되는지 보여주었다. ng-model과 결합된 {{ name }} 지시어를 사용함으로써 데이터 바인딩이 이뤄진다. 데이터바인딩을 하기에 매우 쉽다 . 이 post에서는 여러분들에게 데이터를 저장하는 컨트롤러를 생성하는 과정과 페이지에서 특별한 기능들을 제공하는 컨트롤을 생성할것이다.  이 컨트롤러는 특별한 객체 $scope를 참조하고 의존하고 있다다.  이객체는  "View Model"과 같이 수행되고 이 객체는 프로퍼티 변경에 댛나 모니터링을 담당하고 있다. 이제 ANgularJS컨트롤러를 만드는 단게를 보고 페이지의 엘레먼트에 데이터를 바인딩해보자.

 

Step 1: ng_app 지시어와 AngularJS Script추가

시작하기 위해 ng-ap 지시어를 페이지에 추가하고 AngularJS를 참조하조하자. 여러분은 CDN을 통하여 (https://ajax.googleapis.com/ajax/libs/angularjs/1.0.1/angular.min.js)참조할수 있다.


<!DOCTYPE html>
<html ng-app>
    <head>
        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.1/angular.min.js"></script>
    </head>
    <body>




...
</body>
</
html>

 

Step 2: 컨트롤러와 ViewModel Script 생성


 peopleCtrl.js를  추가하고 아래와 같이 코딩을한다.

 

function PeopleCtrl($scope)  {
    $scope.people = [
        {firstName: 'John', lastName: 'Doe', address: {city: 'Chandler', state: 'AZ', zip: 85248}},
        {firstName: 'Jane', lastName: 'Doe', address: {city: 'Chandler', state: 'AZ', zip: 85248}},
        {firstName: 'Johnny', lastName: 'Doe', address: {city: 'Phoenix', state: 'AZ', zip: 85003}}
    ];

    $scope.addNew = function() {
        $scope.people.push({ firstName: $scope.firstName, lastName: $scope.lastName,
                             address: {city: $scope.city, state: $scope.state, zip: $scope.zip} });
    }
}


이 예제에서는  people 프로퍼티를 정의했고 이 프로퍼티는 object array와 array에 새로운 사람을 추가할수 있는 함수 addNew()를 포함하고 있다.
이 프로퍼티는 View에 바인딩 될것이다. 코드를 살펴보면 여러분은 $scope파라미터가 PeopleCtrl에 전달되는 것을 볼수있다. 이 파라미터는 마치 View와 컨트롤러를 붙여주는 "딱풀"과 같은 역할을 한다. 그리고 모델의 변경을 감시하게 된다. 어떤모델이 변경되었다면 View 또는 컨트롤러에게 이러한 변경내용을 전달하게 된다. (어떤부분에서 모델변경을했는지에 따라 다름) . $scope 파라미터는 자동으로 AngularJS프레임웍에의해 컨트롤러에 전달된다.

$scope 파라미터는 컨트롤러 내부에서 프로퍼티들과 함수를 정의하는데 사용된다. 이러한 기능이 컨트롤러를 View로부터 완전히 분리시키는 역할을 한다. 그리고 unit test 환경을 만들어준다. $scope의 사용은 people과같은 프로퍼티들의 변경을(코드필요없이) 감지하는 역할을 한다. 변경의 감시가 필요한 어떠한 프로퍼티는 $scope를 사용함으로 View에게까지 변경내용이 전달된다. 만약 프로퍼티가 text박스와 같은것에 바인딩 되어있고 어떠한 변경이 엔드 유저에서 발생하면 자동적으로 컨트롤러에 프로퍼티가 업데이트가 된다.  이러한 것은 컨트롤 지향의 코드와는 달리 데이터 지향의 코드를 작성할수 있는 메카니즘을 제공해 준다.

 

Step 3: 페이지에 컨트롤러/ViewModel 정의

컨트롤러에 상으하는 View에  ng-controller 지시어를 아래의 HTML에 추가해 준다.


참고 AngularJS 지시어들은 data-  가 접두사로 사용될수 있다. 예를 들면  data-ng-controller=”PeopleCtrl”는  AngularJS 의 data-ng-app 과 같이 쓰인다. 

 

<div ng-controller="PeopleCtrl">        
    <div id="peopleContainer">



</
div> <div> <h4>Add New Person:</h4> <table style="width: 300px"> <tr> <td style="width: 30%;">First Name:</td> <td style="width: 70%;"><input type="text" ng-model="firstName" /></td> </tr> <tr> <td style="width: 30%;">Last Name:</td> <td style="width: 70%;"><input type="text" ng-model="lastName" /></td> </tr> <tr> <td style="width: 30%;">City:</td> <td style="width: 70%;"><input type="text" ng-model="city" /></td> </tr> <tr> <td style="width: 30%;">State:</td> <td style="width: 70%;"><input type="text" ng-model="state" /></td> </tr> <tr> <td style="width: 30%;">Zip:</td> <td style="width: 70%;"><input type="text" ng-model="zip" /></td> </tr> <tr> <td colspan="2"> <button>Add</button> </td> </tr> </table> </div> </div>


이코드는 컨트롤러참조와 새로운 person을 생성하기위한 텍스트박스들과 버튼들을 다루고 있다. 각 텍스트박스는 ng-model Attribute를 가지고 있어서 쉽게 컨트롤러에서 값들의 접근할수있게 해준다. 텍스트박스의 값들에 접근하는 방법은 다음 스텝에서 볼수 있을것이다.

 

Step 4: people 프로퍼티 값들로 반복하기


 PeopleCtrl가  View에 참조되면 여러분들은 컨트롤러의 people 프로퍼티를 통하여 반복 코드를 사용할수 있을것이다. 반복은 AngularJS의 ng-repeat 지서어를 사용하여 할수 있다.

 

<div id="peopleContainer">
    <ul>
        <li ng-repeat="person in people">
            <span class="bold">{{person.firstName}} {{person.lastName}}</span>
            <br />
            {{person.address.city}}, {{person.address.state}}&nbsp;&nbsp;{{person.address.zip}}
        </li>
    </ul>
</div>


ng-repeat 지서어는 컨터롤러의 people 프로피터안에 객체를 하나씩 반복한다. 그리고 person이라는 이름의 변수에 할당한다. 각 person 객체는 View에 각각 바인딩 되는데 문법은{{person.lastName}} 와 같이 한다. 결과적으로 위의 예저에서는 multiple <li>요소를 다이나믹하게 생성하게 된다.

 

Step 5: 컨트롤러의 함수 호출하기


컨트롤러는 addNew()한수를 가지고 있고 이함수는 Add버튼이 클릭될때 호출이 된다. 버튼의 이벤트를 바인딩하기 위해 ng-click이라는 지시어를 다음과 같이 사용한다 : 

<button ng-click="addNew()">Add</button>

 

버튼이 클릭될때 텍스트 박스에 있는 값들은 $scope를 통해 컨트롤러에 접근할수  있다. 그리고 새로운 person이  people array객체에 추가되게 된다. 이러한 것들은 각 텍스트박스에 ng-model지시어 때문에 가능하게 된다. 

$scope.addNew = function() {
    $scope.people.push({ firstName: $scope.firstName, lastName: $scope.lastName,
                            address: {city: $scope.city, state: $scope.state, zip: $scope.zip} });
}



이 예제에서 우리는 각 텍스트박스 값들은 직접적으로 $scope 변수를 통하여 접근할수 있다. 여기에서 중요한 포인트는 텍스트박스의 값을 찾기 위해 어떠한 코드도 작성하지 않고 값을 추출했다는 것이다. 대신, 우리는 Javascript 데이터 바인딩에 의존하고 있다. 이 스크립트는 많은 코드의 양을 줄이게 해준다.

잘 작동하는 동안 컨트롤러의 people 콜렉션에 새로은 person을 삽입해 준다. ng-model지시어와함게 person. 를쓰게 되면 컨트롤러의  $scope.people.에 자동적으로 person객체가 pepople에 들어가게 된다. 아래를 보면 HTML코드가 어떻게 바뀌었는지 볼수 있다. 텍스트박스에 ng-model 지시어의 변경들을 잘 보아라

<table style="width: 300px">
    <tr>
        <td style="width: 30%;">First Name:</td>
        <td style="width: 70%;"><input type="text" ng-model="person.firstName" /></td>
    </tr>
    <tr>
        <td style="width: 30%;">Last Name:</td>
        <td style="width: 70%;"><input type="text" ng-model="person.lastName" /></td>
    </tr>
    <tr>
        <td style="width: 30%;">City:</td>
        <td style="width: 70%;"><input type="text" ng-model="person.address.city" /></td>
    </tr>
    <tr>
        <td style="width: 30%;">State:</td>
        <td style="width: 70%;"><input type="text" ng-model="person.address.state" /></td>
    </tr>
    <tr>
        <td style="width: 30%;">Zip:</td>
        <td style="width: 70%;"><input type="text" ng-model="person.address.zip" /></td>
    </tr>
    <tr>
        <td colspan="2">
            <button data-ng-click="addNew()">Add</button>
        </td>
    </tr>
</table>

 

이러한것은 아래와 같은 object literal을 자동으로 만들어 준다.

 

{
    firstName: '...',
    lastName: '...'
    address: {
        street: '...',
        city: '...',
        zip: '...'
    }
}



만약 여러분들이 control지향방법을 고려한다면 이 방법은 상당히 효과적이다. 이러한 접근방법으로 addNew()함수는 addNew(person)과같이 바뀔것이다.

 

$scope.addNew = function(person) {
    $scope.people.push(person);
}


 



 아래는 데모입니다. Result탭으로 가서 해보세요