├── .gitignore
├── README.md
├── client
├── index.html
└── js
│ ├── app.js
│ ├── controllers
│ └── TodomvcCtrl.js
│ ├── directives
│ └── todoItem.js
│ └── services
│ └── TodomvcStorage.js
├── gulpfile.js
├── package.json
├── screenshot-preview.png
├── screenshot-structure.jpg
└── server
└── app.js
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | /node_modules
3 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | todomvc-angular
2 | ===============
3 |
4 | ## 미리보기
5 |
6 | 이번 강의에서 만들 결과물을 미리 보자.
7 |
8 | * 투두(Todo) 목록을 조회
9 | * 추가, 편집, 삭제, 완료 처리 (CRUD)
10 | * 투두의 상태에 따라 completed(완료), active(진행중)로 필터링
11 |
12 | 
13 |
14 | ## 프로젝트 구조
15 |
16 | ### 백엔드
17 |
18 | * 서버는 [Node.js](https://nodejs.org/en/)기반의 [Express.js](http://expressjs.com) 웹프레임웍을 사용함
19 | * 서버는 1) html, css, javascript 등의 정적 파일을 호스팅하고 2) ajax 기능을 수행할 api를 제공함
20 |
21 | ### 프론트엔드
22 |
23 | * 웹페이지는 [Angular.js](https://angularjs.org)를 사용한 하나의 페이지(index.html)로 구성됨
24 | * 앵귤러 컨트롤러로 웹페이지를 조작하고 앵귤러 서비스를 통해 백엔드 api와 통신함
25 |
26 | 
27 |
28 | ## 개발 환경
29 |
30 | ### Node.js
31 |
32 | * [https://nodejs.org/en/](https://nodejs.org/en/)에서 다운로드 후 설치
33 | * 웹서버 구동과 프로젝트 관리를 위해 사용
34 |
35 | ### NPM
36 |
37 | * Node Package Manager
38 | * 노드 패키지를 프로젝트에 추가, 삭제하거나 직접 작성한 패키지를 배포할 때 사용함.
39 | * 본 프로젝트에서는 angularjs등 외부 라이브러리 설치시 사용
40 | * 노드를 설치하면 자동으로 NPM도 설치됨
41 | * *이후 Bower, Gulp 등 개발 툴은 상황에 따라 추가 설명할 예정*
42 |
43 | ## 프로젝트 초기화
44 |
45 | * Npm으로 프로젝트 초기화
46 |
47 | ```
48 | $ mkdir todomvc && cd todomvc
49 | $ npm init
50 | ```
51 |
52 | * package.json: 프로젝트 정보를 담고 있음.
53 | * 특히 dependencies에는 프로젝트에서 사용하는 외부 라이브러리 정보가 기록됨
54 |
55 | ## 앵귤러 시작
56 |
57 | * index.html 작성
58 |
59 | ```html
60 |
61 |
62 |
63 |
64 |
65 |
67 | Angular | TodoMVC
68 |
69 |
70 |
71 |
72 | ```
73 |
74 | * Npm 으로 앵귤러 설치:
75 |
76 | ```
77 | $ npm install angular --save
78 | ```
79 | * save 옵션을 주는 것은 이 프로젝트가 앵귤러 라이브러리를 사용한다는 것을 알리는 것
80 | * 이 정보는 package.json의 dependencies에 추가됨
81 | * 앵귤러 라이브러리를 로딩하고 **모듈(module)**, **컨트롤러(controller)** 생성
82 | * `ng-app`: 브라우져에게 앵귤러 모듈을 사용한다고 알림
83 | * `ng-controller`: 브라우져에게 앵귤러 컨트롤러를 사용한다고 알림
84 |
85 | ```html
86 |
87 |
88 |
89 |
90 |
91 |
98 |
99 |
100 | ```
101 |
102 | ## [TIP] brower-sync
103 |
104 | * [bower-sync](https://www.browsersync.io/)는 코드변호에 따라 브라우져를 리프레시 해주는 툴
105 | * 내부적으로 웹서버를 구동함
106 | * Npm을 이용해 글로벌로 설치
107 |
108 | ```
109 | $ npm install -g browser-sync
110 | $ browser-sync start --server --files "./**/*"
111 | ```
112 |
113 | ## Controller
114 |
115 | * Html로 작성된 템플릿과 연결되어 데이터를 출력하고 사용자 입력을 처리하는 것이 컨트롤러의 역할
116 | * `angular.module().controller()` 함수로 컨트롤러 정의
117 |
118 | ```javascript
119 | // js/controllers/TodomvcCtrl.js:
120 | angular.module('todomvc')
121 | .controller('TodomvcCtrl', function ($scope) {
122 | $scope.message = 'Hello world!';
123 | });
124 | ```
125 |
126 | * 컨트롤러스 생성과 동시에 스코프 변수(`$scope`)가 자동으로 생성됨
127 | * 이는 템플릿과 컨트롤러간의 연결을 위한 변수임
128 | * index.html에 스코프 변수 출력하기 (인터폴레이션)
129 |
130 | ```html
131 |
132 |
133 |
134 | {{ message }}
135 |
136 |
137 |
138 | ```
139 |
140 | ## 투두 목록 출력하기 (ngRepeat)
141 |
142 | * 컨트롤러에 배열 데이터 `$scope.todos` 만들기
143 |
144 | ```javascript
145 | // js/controllers/TodomvcCtrl.js
146 | angular.module('todomvc')
147 | .controller('TodomvcCtrl', function ($scope) {
148 | $scope.todos = [{
149 | id: 1,
150 | title: '요가 수행하기',
151 | completed: false
152 | }, {
153 | id: 2,
154 | title: '어머니 용돈 드리기',
155 | completed: true
156 | }];
157 | });
158 | ```
159 |
160 | * `ngRepeat`으로 배열 출력하기
161 |
162 | ```html
163 |
164 |
171 | ```
172 |
173 | ## 삭제 기능 만들기 (ngClick)
174 |
175 | * ngClick 디렉티브를 이용해 버튼의 클릭 이벤트 후킹
176 |
177 | ```html
178 |
179 |
180 |
181 | ```
182 |
183 | * ngClick에 설정한 컨트롤러 함수를 이용해 이벤트 핸들러 구현
184 |
185 |
186 | ```javascript
187 | // js/controllers/TodomvcCtrl.js
188 | angular.module('todomvc')
189 | .controller('TodomvcCtrl', function ($scope) {
190 | $scope.remove = function (id) {
191 | if (!id) return;
192 |
193 | // 배열에서 제거할 인덱스를 검색
194 | var deleltedTodoIdx = $scope.todos.findIndex(function (todo) {
195 | return todo.id === id;
196 | });
197 |
198 | if (deleltedTodoIdx === -1) return;
199 |
200 | // 배열에서 제거
201 | $scope.todos.splice(deleltedTodoIdx, 1);
202 | }
203 |
204 | });
205 | ```
206 |
207 | ## 새로운 투두 추가하기 (ngForm)
208 |
209 | * 앵귤러로 폼 작성하기
210 | * 폼에서 submit 이벤트 발생시 ngSubmit 디렉티브에 설정한 컨트롤러 함수가 동작하는 구조
211 | * 폼버튼을 만들고 ngSubmit에 컨트롤러 함수를 연결
212 |
213 | ```html
214 |
215 |
219 | ```
220 |
221 | * ngSumbit에 연결된 컨트롤러 함수 구현
222 |
223 | ```javascript
224 | // js/controllers/TodomvcCtrl.js
225 | angular.module('todomvc')
226 | .controller('TodomvcCtrl', function ($scope) {
227 | $scope.addTodo = function (title) {
228 | title = title.trim();
229 | if (!title) return;
230 |
231 | // 새로 추가할 아이디 계산
232 | var newId = !$scope.todos.length ?
233 | 1 : $scope.todos[$scope.todos.length - 1].id + 1;
234 |
235 | // 새로운 투두 객체
236 | var newTodo = {
237 | id: newId,
238 | title: title,
239 | completed: false
240 | };
241 |
242 | // todos 배열에 새로운 투두 추가
243 | $scope.todos.push(newTodo);
244 | };
245 | });
246 | ```
247 |
248 | ## 스타일 입히기 (Twitter Bootstrap)
249 |
250 | * [Twitter Bootstrap](http://getbootstrap.com)은 반응형웹, 모바일 웹을 위한 스타일시트 라이브러리
251 | * Npm으로 부트스트랩 설치
252 |
253 | ```
254 | $ npm instsall bootstrap --save
255 | ```
256 | * index.html에 라이브러리 로딩
257 |
258 | ```html
259 |
260 |
261 | ```
262 |
263 | * 부트스트랩 클래스 적용하기
264 |
265 | ```html
266 |
267 |
268 |
269 |
270 |
271 |
273 | Angular | TodoMVC
274 |
276 |
277 |
278 |
279 |
Todos
280 |
281 |
294 |
295 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 | ```
317 |
318 | ## 7. 투두 목록 필터링
319 |
320 | * 출력된 투두목록을 아래 기준으로 필터링해 보자
321 | * `completed`: 완료된 투두 리스트
322 | * `active`: 미완료된 투두 리스트
323 | * `all`: 모든 투두 리스트
324 |
325 | * `ngRepeat`의 필터링 기능
326 | * index.html:
327 |
328 | ```html
329 |