2019. 4. 3. 18:37ㆍFrontend/AngularJS
해당 포스트는 Inflearn AngularJS 강좌를 기반으로 작성되었으며, 언급되는 개념 및 실습 과정을 담았습니다.
따라서, 코드는 단계적으로 작성되어 이전 코드와 연결되어 있습니다.
AngularJS
1. AngularJS 개념
공식 페이지의 Coceptual Overview를 보면 개념들이 정의되어 있다.
Directives
: 확장된 HTML로,custom 속성
과elements
를 뜻함directives
를 사용해 직접 태그를 정의할 수 있다.
Expressions
: HTML에서 JS의 데이터를 출력해야 하는 경우 사용
1.// html
2.
3.<!--{{ name }}` 부분에 지정한 데이터가 삽입됨-->
4.<p>hello {{ name }}</p>
Module
기능적으로 비슷한 것들을 모아 모듈을 만듦.
의존관계가 있을 경우 다른 모듈을 주입해서 사용 가능
Controller
HTML 뒷 단에 위치.
HTML View를 조작함.
View의 비즈니스 로직을 구현하는데만 사용해야 한다.
Service
(
Controller
와 다르게) 재 사용할 수 있는 비즈니스 로직싱글톤으로 구현되어 있음
어플리케이션 데이터를 다루는데 사용
참고
AngularJS 전체 구성 요소
AngularJS 흐름
개발 환경 구성
강의는 Plunker를 사용해서 개발하지만, 나는 Codepen을 사용해서 개발할 예정
2. Controller
index.html로 시작하기
ng-app
선언하는 부분부터 앵귤러를 사용하겠다고 알려주는 역할
앵귤러 쪽에서는 angular Directive를 찾아 해석함
ng-init
변수나 함수를 초기화 함
expression 식(
{{ }}
기호)을 사용해 표현
index.html
1.<html>
2. <head>
3. <!-- bootstrap -->
4. <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
5. <!-- angularjs -->
6. <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
7. </head>
8.
9. <body ng-app ng-init="name = 'mizzo'">
10. <h1>Hello {{ name }}!</h1>
11. </body>
12.</html>
실행결과
module & controller & 출력하기
모듈
하나의 큰 컨테이너 (컨트롤러, 액티브, 서비스 등 포함)
컨테이너
View의 비즈니스 로직을 구현하는데 사용
$scope
: controller와 html간의 연결고리 역할
script.js
1.(function() {
2. // 배열을 파라미터로 받는 todo라는 angular module을 생성해준다.
3. var app = angular.module('todo', []);
4.
5. // 컨트롤러를 todo라는 모듈 안에 생성해야 한다. -> app.controller
6.
7. // TodoCtrl라는 이름을 가진 컨트롤러를 생성한다.
8. app.controller('TodoCtrl', ['$scope', function ($scope) {
9. $scope.name = 'mizzo';
10. }]);
11.})();
index.html
1.<html>
2. <head>
3. <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
4. <link rel="stylesheet" href="style.css">
5. </head>
6.
7. <!-- ng-controller로 위에 만든 컨트롤러를 연결한다-->
8. <body ng-app="todo" ng-controller="TodoCtrl">
9. <!-- scope의 name을 표현하자 -->
10. <h1>Hello {{ name }}!</h1>
11.
12.<!-- 습관적으로라도 스크립트는 바디가 끝나기 직전에 호출하자. -->
13. <script src="script.js"></script>
14. </body>
15.</html>
실행결과
실제 프로젝트에선 object를 주고 받을 것.
todo object를 만들고 표현해보자.
script.js
1.(function() {
2. var app = angular.module('todo', []);
3.
4. app.controller('TodoCtrl', ['$scope', function ($scope) {
5. //object를 만들어 주고 받자
6. $scope.todo = {
7. title: '요가 수련',
8. completed: false,
9. createdAt: Date.now()
10. }
11. }]);
12.})();
index.html
1.<html>
2. <head>
3. <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
4. <link rel="stylesheet" href="style.css">
5. </head>
6.
7. <body ng-app="todo" ng-controller="TodoCtrl">
8. <h1>Todo</h1>
9.
10. <!-- object 그대로를 출력한다. -->
11. {{ todo }}
12.
13. <!-- object 내의 변수를 각각 출력 -->
14. <h3>{{ todo.title }}</h3>
15. <p>{{ todo.completed }}</p>
16. <date>{{ todo.createdAt }}</date>
17. <script src="script.js"></script>
18. </body>
19.</html>
실행 결과
엔진모델은 양방형 바인딩이다.
대표적인 예로, input
태그와 ng-model
directive를 활용해 변경된 데이터를 js 변수 object에 바인딩할 수 있다.
script.js 파일은 그대로 두고 html만 수정해보자
index.html
1.<html>
2. <head>
3. <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
4. <link rel="stylesheet" href="style.css">
5. </head>
6.
7. <body ng-app="todo" ng-controller="TodoCtrl">
8. <h1>Todo</h1>
9.
10. <!-- todo의 title이 그대로 반영된다. -->
11. <input type="text" ng-model="todo.title">
12. <!-- todo의 completed이 그대로 반영된다. -->
13. <input type="checkbox" ng-model="todo.completed">
14.
15. <!-- todo object 그대로 출력하여 실시간으로 바인딩되는 것을 확인하자 -->
16. {{ todo }}
17. <script src="script.js"></script>
18. </body>
19.</html>
실행 결과
실시간으로 text와 체크 여부를 변경할 때마다 출력되는 데이터가 달라지는 것을 확인할 수 있다.
3. 내장 Directive
ng-repeat
배열과 함께 사용하면 좋음
반복문 처럼 사용할 수 있다.
todos라는 배열에 todo object 들을 넣어두고
html에서 ng-repeat
을 사용해 불러오자.
script.js
1.var app = angular.module('todo', []);
2.
3.app.controller('TodoCtrl', function($scope) {
4. $scope.todos = [
5. {
6. title: '요가 수업',
7. completed: false,
8. createdAt: Date.now()
9. },
10. {
11. title: '앵귤러 학습',
12. completed: false,
13. createdAt: Date.now()
14. },
15. {
16. title: '운동하기',
17. completed: true,
18. createdAt: Date.now()
19. }
20. ]
21.});
index.html
1.<html>
2. <head>
3. <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
4. <link rel="stylesheet" href="style.css">
5. </head>
6.
7. <body ng-app="todo" ng-controller="TodoCtrl">
8. <h1>Todo</h1>
9.
10. <ul>
11. <!-- todo는 todos 안의 한 object를 가르키는 커서이다. -->
12. <li ng-repeat="todo in todos">
13. <input type="text" ng-model="todo.title">
14. <input type="checkbox" ng-model="todo.completed">
15. <date>{{ todo.createdAt }}</date>
16. </li>
17. </ul>
18.
19. <script src="script.js"></script>
20. </body>
21.</html>
실행 결과
Bootstrap 적용해서 더 예쁘게 해보자
css > typography > unstyled 적용해서 앞에 리스트 점 없애 주기
index.html
1.<html>
2.
3.<head>
4. <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
5. <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
6. <link rel="stylesheet" href="style.css">
7.</head>
8.
9.<body ng-app="todo" ng-controller="TodoCtrl">
10. <h1>Todo</h1>
11.
12. <!-- unstyled 적용 -->
13. <ul class="list-unstyled">
14. <li ng-repeat="todo in todos">
15. <!-- checkboxes-and-radios 적용 -->
16. <div class="input-group mb-3">
17. <div class="input-group-prepend">
18. <div class="input-group-text">
19. <input type="checkbox" ng-model="todo.completed">
20. </div>
21. </div>
22. <input type="text" ng-model="todo.title">
23. </div>
24. <date>{{ todo.createdAt }}</date>
25. </li>
26. </ul>
27.
28. <script src="script.js"></script>
29.</body>
30.
31.</html>
실행 결과
ng-filter
표현식을 사용해 일정한 포맷으로 만들어줄 수 있다.
커스텀 필터를 생성해 원하는 값만 필터링 해줄 수 있다.
angularJS의 기본 date filter를 사용해 date를 예쁘게 출력할 것
문서를 보니 html에서는 아래 양식을 사용해서 필터 적용
1.{{ date_expression | date : format : timezone}}
index.html에 date 부분만 아래 코드로 변경한다.
index.html
1.<date>{{ todo.createdAt | date : 'yyyy-MM-dd HH:mm:ss'}}</date>
실행 결과
ng-Click
button에 추가하여 click 했을 때 실행시킬 함수를 지정할 수 있다.
실습
todo 항목에 삭제 버튼을 추가할 것이다.
부트스트랩 components > input-group > button-addons에 있는 오른쪽 버튼 부분을 가져와 더해주자
그리고 다음과 같이 수정했다.
class = btn-danger
로 수정해 빨간색 위험한 UI를 표현했다. (기본 설정 값 이용)ng-click = remove()
를 지정해 버튼이 클릭 됐을 때todo
모듈의TodoCtrl
컨트롤러안에 선언한remove
함수를 호출할 것이다.
index.html
1.<html>
2.
3.<head>
4. <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
5. <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
6. <link rel="stylesheet" href="style.css">
7.</head>
8.
9.<body ng-app="todo" ng-controller="TodoCtrl">
10. <h1>Todo</h1>
11.
12. <ul class="list-unstyled">
13. <li ng-repeat="todo in todos">
14. <div class="input-group mb-3">
15. <div class="input-group-prepend">
16. <div class="input-group-text">
17. <input type="checkbox" ng-model="todo.completed">
18. </div>
19. </div>
20. <input type="text" ng-model="todo.title">
21. <!-- addon 버튼 추가 부분-->
22. <div class="input-group-append">
23. <button class="btn btn-danger" type="button" ng-click="remove()">삭제</button>
24. </div>
25. <!-- -->
26. </div>
27. <date>{{ todo.createdAt | date : 'yyyy-MM-dd HH:mm:ss'}}</date>
28. </li>
29. </ul>
30.
31. <script src="script.js"></script>
32.</body>
33.
34.</html>
버튼이 눌릴 때 호출될 함수를 만들어준다.
todo
모듈의TodoCtrl
컨트롤러안에remove
함수를 선언한다.간단하게 눌렸는지 확인하기 위해 경고창을 띄워주자.
script.js
1.var app = angular.module('todo', []);
2.
3.app.controller('TodoCtrl', function($scope) {
4. $scope.todos = [
5. {
6. title: '요가 수업',
7. completed: false,
8. createdAt: Date.now()
9. },
10. {
11. title: '앵귤러 학습',
12. completed: false,
13. createdAt: Date.now()
14. },
15. {
16. title: '운동하기',
17. completed: true,
18. createdAt: Date.now()
19. }
20. ];
21.
22. // 매개변수가 없는 remove 함수를 선언한다.
23. $scope.remove = function() {
24. alert();
25. }
26.});
실행결과
삭제 버튼 눌렀을 때의 화면
이제 진짜 버튼이 눌렸을 때 삭제되도록 구현해보자.
id
를 비교하여 삭제하고자 하는 객체의index
를 찾는다.splice
함수를 이용해 객체 배열에서 특정 객체를 삭제한다.
script.js
1.var app = angular.module('todo', []);
2.
3.app.controller('TodoCtrl', function($scope) {
4. // 코드 생략
5. ...
6.
7. $scope.remove = function(todo) {
8. // todos 배열에서 todo index를 찾는다.
9. var idx = $scope.todos.findIndex(function (item) {
10. return item.id == todo.id;
11. });
12.
13. // idx가 유효할 때 삭제해준다.
14. if (idx > -1) {
15. // 배열 객체에서 제공되는 함수인 splice를 이용하면 원하는 위치에 요소를 삭제할 수 있다.
16. // idx 위치부터 1개의 요소를 삭제한다.
17. $scope.todos.splice(idx, 1)
18. }
19. }
20.});
실행 결과
첫번째 삭제 버튼을 눌렀을 때 결과
Filter Button
버튼을 눌렀을 때 각 조건에 따라 TODO 리스트가 필터링된 결과를 출력하도록 구현해볼 것이다.
이를 구현하기에 앞서,
이전에 배웠던 filter 기능을 사용해 기존 리스트를 필터링할 수 있다.
index.html
1.<!-- completed가 true인 값들만 출력한다. -->
2.<li ng-repeat="todo in todos | filter:{completed : true}">
실행 결과
이 기능을 활용해 필터 버튼을 구현할 것인데,
필터에 변수를 지정해두고 케이스별로 다른 값을 넣어주어 필터링 조건을 변경할 것이다.
index.html
1.<html>
2.
3.<head>
4. <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
5. <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
6. <link rel="stylesheet" href="style.css">
7.</head>
8.
9.<body ng-app="todo" ng-controller="TodoCtrl">
10.
11. <!-- 기존 코드를 컨테이너에 담았다. -->
12. <div class="container">
13. <h1>Todo</h1>
14.
15. <ul class="list-unstyled">
16. <!-- statusFilter라는 변수를 지정해주자 -->
17. <li ng-repeat="todo in todos | filter: statusFilter">
18. <div class="input-group mb-3">
19. <div class="input-group-prepend">
20. <div class="input-group-text">
21. <input type="checkbox" ng-model="todo.completed">
22. </div>
23. </div>
24. <input type="text" ng-model="todo.title">
25. <div class="input-group-append">
26. <button class="btn btn-danger" type="button" ng-click="remove(todo)">삭제</button>
27. </div>
28. </div>
29. <date>{{ todo.createdAt | date : 'yyyy-MM-dd HH:mm:ss'}}</date>
30. </li>
31. </ul>
32.
33. <!-- 필터 버튼 선언 부분 -->
34. <!-- ng-click에 statusFilter값을 변경해주는 코드를 넣는다 -->
35. <button class="btn btn-primary" ng-click="statusFilter = {completed : true}">Completed</button>
36. <button class="btn btn-primary" ng-click="statusFilter = {completed : false}">Active</button>
37. <button class="btn btn-primary" ng-click="statusFilter = {}">All</button>
38. </div>
39.
40. <script src="script.js"></script>
41.</body>
42.
43.</html>
실행 결과
completed 버튼 클릭 | Active 버튼 클릭 | All 버튼 클릭 |
참고 사이트