컨트롤러에 배열 데이터 만들기

우선 데이터가 있다고 가정하자. 우리 프로젝트에서 데이터는 투두 목록이다. 하나의 두투는 아이디(id), 타이틀(title), 그리고 완료여부(completed)를 데이터로 가질 수 있고 컨트롤러에서 아래와 같이 표현할 수 있다.

js/controllers/TodomvcCtrl.js:

angular.module('todomvc')
    .controller('TodomvcCtrl', function ($scope) {

      $scope.todos = [{
        id: 1,
        title: '요가 수행하기',
        completed: false
      }, {
        id: 2,
        title: '어머니 용돈 드리기',
        completed: true
      }];

    });

스코프변수에 할당된 todos 배열을 템플릿에 어떻게 출력할 수 있을까? 그냥 한번 출력해 보자. 자바스크립트의 console.log() 함수처럼 앵귤러에서 {{json}}으로 출력하면 데이터 내용을 직접 화면에서 볼 수 있다. 개인적으로 디버깅용으로 많이 사용한다. (물론 앵귤러를 위한 크롬 개발자 툴이 있긴하다.)

index.html:

<div ng-controller="TodomvcCtrl">
      <h1>Todos</h1>
      <pre>{{todos | json}}</pre>
</div>

ngRepeat으로 배열 출력하기

ngRepeat은 자바스크립트 배열을 출력하기 좋은 앵귤러 디렉티브이다. 스코프변수에 할당된 todos 배열을 ngRepeat으로 출력해 보자.

index.html:

<ul ng-repeat="todo in todos track by $index">
  <li>
      <input type="checkbox" ng-model="todo.completed">
      <input type="text" ng-model="todo.title">
      <button type="button">Remove</button>
  </li>
</ul>

문법이 조금 복잡하게 보일지 모르겠으나 이렇게 사용하는 것이 맞다.

ng-repeat="todo in todos"는 자바스크립트의 for/in 문법과 비슷하다. 그리고 그 반복문 안에서 todo는 배열안의 하나의 todo 데이터와 동일하다. 루프에서는 checkbox, text, button 세 개의 입력 필드를 만들었다.

체크박스는 완료 여부를 표현하는 todo.completed와 연결시켰다. ng-model 디렉티브를 사용한 것이 보이는가? 이것은 앵귤러에서 양방향 데이터 바인딩을 가능하게 하는 기능이다. 즉 템플릿에서 사용자가 데이터를 변경하면 컨트롤러 데이터가 변경되고, 반대로 컨트롤러 데이터가 변경되면 템플릿에도 그대로 반영된다. 참고롤 단방향 바인딩은 ng-bind를 사용한다.

다음 텍스트 인풋 필드에서는 todo 타이들인 todo.title 데이터와 연결되어 있다. 체크박스와 동일하게 ng-model로 양방향 바인딩 되어 인풋필드를 수정하면 컨트롤러의 스코프 변수에 바로 반영된다.

마지막에는 투두를 삭제할수 있는 버튼을 만들었다. 실제 동작하지는 않지만 나중에 ng-click 이라는 디렉티브를 사용하여 이벤트 처리를 구현할 것이다.

결과를 확인해 보자.

ngClick으로 삭제기능 만들기

각 투두에 삭제 버튼을 추가해 보자. 기억하는가? 우리는 버튼 클릭 이벤트를 받기위해 ng-click 디렉티브를 사용할 수 있다.

<ul ng-repeat="todo in todos">
  <li>
      <input type="checkbox" ng-model="todo.completed">
      <input type="text" ng-model="todo.title">

      <!-- ng-click 디렉티브로 컨트롤러의 remove() 함수와 연결했다. -->
      <button type="button" ng-click="remove(todo.id)">Remove</button>
  </li>
</ul>

ng-click 디렉티브로 컨트롤러의 remove() 함수와 연결했다. 그리고 삭제할 투두의 id를 파라메터로 넘겨 줬다. 여기서 todo.id에 접근할 수 있는 것은 ng-repeat 반복문 안에 있기 때문이다.

이제 컨트롤러에서 remove() 함수를 만들어 만들면 삭제 기능을 구현할 수 있다. 그리고 템플릿에서 사용할 수 있으려면 todos 배열과 마찬가지고 스코프 변수에 추가해야 한다.

angular.module('todomvc')
    .controller('TodomvcCtrl', function ($scope) {

      $scope.remove = function (id) {
        if (!id) return;

        // 배열에서 제거할 인덱스를 검색
        var deleltedTodoIdx = $scope.todos.findIndex(function (todo) {
          return todo.id === id;
        });

        if (deleltedTodoIdx === -1) return;

        // 배열에서 제거
        $scope.todos.splice(deleltedTodoIdx, 1);
      }

    });

관련글:

  1. [앵귤러로 Todo앱 만들기] 노드 설치
  2. [앵귤러로 Todo앱 만들기] 앵귤러 로딩
  3. [앵귤러로 Todo앱 만들기] 컨트롤러
  4. [앵귤러로 Todo앱 만들기] 투두 목록 출력하기
  5. [앵귤러로 Todo앱 만들기] 새로운 투두 추가하기
  6. [앵귤러로 Todo앱 만들기] Bootstrap으로 꾸미기
  7. [앵귤러로 Todo앱 만들기] 투두 목록 필터링
  8. [앵귤러로 Todo앱 만들기] Directive
  9. [앵귤러로 Todo앱 만들기] Service
  10. [앵귤러로 Todo앱 만들기] Express.js로 웹서버 만들기
  11. [앵귤러로 Todo앱 만들기] Static File
  12. [앵귤러로 Todo앱 만들기] APIs
  13. [앵귤러로 Todo앱 만들기] $http로 앵귤러 서비스 개선하기