반응형
Angular Tutorial
아래 튜토리얼은 4~8
- Displaying a List
- Master/Detail Components
- Services
- Master/Detail Components
- Services
- Routing
- HTTP
Displaying a List
- Heroes의 리스트를 보여주고, hero 선택 및 hero의 details까지!
- Create mock Heroes
- 실제로는 remote data server로 부터 데이터를 가져와야 하지만, mock heroes를 만들어서 서버에서 동작하듯
- mock-heroes.ts를 src/app/ 폴더에 생성
- Displaying heroes
- HeroesComponents에 보여주기 위해서
- 위에서 생성한 mock-heroes를 import
- 그런다음 heroes의 property에 heroes를 가리키도록 바인딩
- List heroes with ngFor
- HeroesComponent template file 열고 변경 li, ul태그 추가
- ngFor는 angular's repeater
- Style the heroes
- heroes list는 attractive해야 하고, 유저가 마우스를 리스트 위에 올리거나, 선택할때 visually 응답이 있어야 한다.
- 전체 스타일을 적용하기 위해서는 styles.css
- heroes.component.ts에 heroes.component.css스타일을 적용해야 한다.
- Master/Detail
- master list에 있는 hero를 유저가 클릭했을때, page아래 hero's details이 표시 되어야 한다.
- Add a click event binding
- li에 click event를 binding 하기 위해서 (click)="onSelect(hero)"를 추가
- Add the click event handler
- application이 최초에 추가 되었을때는 아무것도 선택된 내용이 없을 것이다.
- onSelect() 함수에 clicked hero를 selecdtedHero에 assign해준다.
- Update the details template
- 이전 hero의 property는 더이상 존재하지 않기 때문에 hero를 selectedHero로 rename
- Hide empty details with ngif
- 새로고침을 하게 되면, seletecedHero가 undefined되도록 디자인 되었기 때문에 에러가 발생한다.
- ngIf를 통해서 selectedHero에 값이 undefined되어 있으면 hero detail이 보이지 않도록 조건을 추가
- Style the selected hero
- li중에 선택된 항목에 대해서 특정색을 보여줘야 한다.
- .selected CSS class를 사용하면 된다.
Master/Detail Components
- large components를 smaller sub-components로 나누는 방법에 대해서 설명
- HeroDetailsComponent를 reusable
- Make the HeroDetailComponent
- hero-detail component를 Angular CLI를 통해 생성하자.
- Wrtie the template
- HeroesComponent의 아래에 있는 hero detail을 HeroDetailComponent에 옮기자
- Add the @Input() hero property
- HeroDetailComponent template에서 hero property를 binding하기 위해서 hero를 import
- hero property는 input property여야하고, @Input() decroator 이여야지만 외부 HeroesComponent에서 bind를 할 수 있다.
- hero-detail.components.ts에 Input을 import하고, @Input() hero: Hero;
- Show the HeroDetailComponent
- HeroesComponent는 아직 master/detail view이다.
- HerosComponent는 parent로 child HeroDetailComponent를 관리하게 된다. (리스트에서 어떤 히어로가 선택이 되었을때 보여질 새로운 hero를 전달)
- Update the HeroesComponent template
- HeroDetailComponent selector는 app-hero-detail
element를 HeroesComponents template 아래에 추가 - HeroesComponent.selectedHero를 hero property로 binding
- 위 처럼 binding을 하면 HeroComponent에서 선택된 selectedHero는 HeroDetailComponent에 업데이트되고 새로운 hero의 detail을 보여줄 것이다.
- What Changed?
- 기존에 HerosComponent에서 모든것을 처리했다면, 지금은 HeroDetailComponent에서 대신 hero의 detail을 보여주고 있다.
- 기존 HeroesComponent를 Refactoring
- HeroesComponent의 역할을 줄였다.
- HeroesComponent의 수정 없이 HeroDetailComponent의 수정을 통해 rich hero editor로 수정이 가능
- HeroesComponent를 hero detail view 수정 없이 수정 가능
- 이후 컴포넌트에서 HeroDetailComponent를 re-use 가능하다
Services
- HeroesComponent는 현재 fake data를 통해서 getting and displaying을 하고 있다.
- HeroesComponent에서 서비스 단위 테스트를 하는것에 대해서 설명한다.
- Why Services
- Components는 fetch, save data를 직접 처리하면 안된다. component는 data를 제공하고, 서비스에 data를 delegate하는데 초점을 맞춰야 한다.
- HeroService를 생성해서 모든 application classes에서 heroes를 가져올 수 있도록 한다.
- 새로운 서비스를 angular dependency injection을 이용해 생성하고, HeroesComponent constructor에가 inject한다.
- services는 서로 알지 못하는 classes 사이에 정보를 공유하는데 좋은 방법이다.
- MessageService를 생성하고, 두개의 장소에 inject
- HeroService: send message하는데 사용
- MessageComponent: message를 display
- Create the HeroService
- Angular CLI를 사용해 hero service를 생성
- $ ng generate service hero
- skeleton HeroService class를 생성한다. (src/app/hero.service.ts)
- @Injectable() services
- 새로운 서비스 injectable
- get hero data
- HeroService는 어디서든 hero 데이터를 가져올 수 있다. (web, local storage, mock data source 등등)
- data access를 components에서 제거한다고 해도, 어떤 다른 component의 수정없이 서비스만 동작을 변경시키면 된다.
- Provide the HeroService
- Dependency injection system에서 HeroService를 제공해야 Angular가 HeroesComponentdㅔ inject를 할 수 있다.
- HeroesComponent, AppComponent, AppModuel에서 HeroService를 제공하기 위한 방법이 여러가지 있다. 각각의 장단점이 있는데,
- 이 tutorial에서는 AppMoudle에서 제공
- CLI를 통해
- $ ng generate service hero --module=app
- AppModule class를 열어서 HeroService를 @NgModule.providers array에 import
- providers array는 HeroSerivce의 single shared instance를 생성하고, class에 inject하도록 angular에게 지시하는 역할을 한다.
- HeroService는 이제 HeroesCoponent에 plug into 될 준비가 되었다.
- Update HeroesComponent
- HeroesComponent에서 HEROES는 이제 더이상 사용하지 않기 때문에 제거하고, HeroService를 대신 추가하자.
- Inject the HeroService
- heroService를 추가
- Angular에서 HeroesComponent를 생성할때 Dependency Injection system에서는 heroService를 HeroService의 singleton intance로서 세팅
- Add getHeroes()
- service로 부터 heroes를 retrieve하는 function을 생성.
- Call it in ngOnInit
- 생성자에서 getHeroes()를 호출하는 방법은 좋은 방법이 아니다.
- constructor는 단순한 초기화만 진행되어야 하고, HTTP request를 생성해 remote server에서 실제 데이터를 가져오는 기능은 하면 안된다.
- 대신 getHeroes()는 ngOnInit lifecycle hook에서 호출이 되어야 한다. Angular에서는 ngOnInit을 HeroesComponent instance가 생성된 이후에 적절한 시점에서 호출을 한다.
- Observable data
- HeroService.getHeroes() method는 synchronous signature를 갖고 있기 때문에 HeroService는 heroes를 synchronously fetch를 할 수 있다.
- heroService는 서버로 부터 응답을 기다려야만 하기 때문에, getHeroes()를 통해 즉시 hero data를 받아올 수 없다. 결과적으로는 service가 완료될때까지 브라우저는 동작하지 않는다.
- Heroservice.getHeroes()는 asynchronous signature여야만 한다.
- callback을 사용해서 해결
- Observable HeroService
- Observable은 RxJS library의 key class중 하나이다.
- 이후에 HTTP tutorial에서는 Angular's HTTPClient methods return RxJS Observable에 대해서 알아볼 것이다.
- 여기에서는 simulate getting data from the server with the RxJS of() function
- HeroService file을 열고 RxJS로부터 Observable과 of symbols를 import
- getHeroes method를 변경한다.
- Subscribe in HeroesComponent
- HeroService.getHeroes method는 Hero[]를 리턴하는데, 위 처럼 변경하면 Observable
- Observable.subscrbie()는 critical하게 다르다.
- 이전 버전에서 component's heroes property에 heroes의 array를 assign했다. 그 assignment는 synchronously를 발생하게 된다.
- 위 문제로 server의 응답으로부터 기다려야 하기 때문에 UI는 freeze된다.
- 새로우 버전은 Observable을 기다린다. 기다린 이후에 subscribe는 array를 callback을 통해 pass를 한다. 이과정을 통해서 heroes property에 set이 된다.
- 위 asynchronous approach는 HeroService에서 서버로부터 heroes를 requests할때 사용하면 된다.
- HeroService.getHeroes method는 Hero[]를 리턴하는데, 위 처럼 변경하면 Observable
- Show message
- 이번 섹션에서는
- screen의 아래 부분에 위치하는 app messages를 보여주는 MessagesComponent를 추가
- displayed되는 message를 보내기 위해 injectable, app-wide MessageService를 생성
- HeroService에 MessageService를 inject
- HeroService가 heroes를 성공적으로 fetches할때 message를 화면에 표시
- Create MessagesComponent
- CLI를 통해 MessagesComponent를 생성
- $ ng generate component message
- AppComponent template에서 MessagesComponent가 보이도록 수정
- Create The MessageService
- CLI를 통해 messageService를 생성
- $ ng generate service message --module=app
- MessageService의 내용을 수정
- Inject it into the HeroService
- HeroService에 MessageService를 import
- Send a message from HeroService
- getHeroes method에 heroes가 fetch 되었을때 send message 로직 추가
- Display the message from HeroService
- MessagesComponent는 모든 messages를 출력을 해야한다.
- MessageComponent에 MessageService를 import
- messageService property는 반드시 public으로 해야 다른 templatedㅔ서도 binding해서 사용 가능
- Bind to the Message Service
- mesageComponent template를 수정
Routing
- Tour of Heroes app의 requirements
- Add Dashboard view
- Heroes, Dashboard views사이에 navigat
- view에서 hero를 클릭하면, selected hero의 detail view가 보이도록
- email에 있는 deep link를 클릭할때, 특정 영웅에 대한 세부정보보기를 열도록
- Add the AppRoutingModule
- Angular에서 best practice는 toload and configure the router in a separate, top-level module that is dedicated to routing and imported by the root AppModule.
- module class이름을 AppRoutingModule, app-routing.module.ts는 src/app folder에 위치
- CLI를 통해 생성
- $ ng generate module app-routing --flat --module=app
- flat은 its own folder대신에 src/app에 위치하도록
- --module=app은 AppModule의 array에 register
- Add Routes
- Routes는 user가 클릭한 link 또는 browser address bar에 URL을 붙여넣었을때 보여지는 화면을 의미한다.
- Angular Route는 two properties를 가지고 있다.
- path: address bar에 있는 URL과 match되는 string
- component: router로 navigating할때 생성되는 component
- HeroesComponent를 navigate한다고 의도할때, URL은 localhost:4200/heroes
- HeroesComponent를 import하고, Routes에 path로 heroes, component로 HeroesComponent를 추가하면 된다.
- RouterModule.forRoot()
- router는 반드시 처음 초기화를 하고, browser location changes를 listening해야한다.
- RouterModule을 @NgModule.imports array에 추가하고, routes를 RouterModule.forRoot()내에 호출한다.
- Add RouterOutlet
- AppComponent template에서
의 elements를 element로 변경
- Add a navigation link(routerLink)
- User는 항상 URL을 복사해서 붙여넣지 않고, navigate하기 위해서는 클릭을 한다.
- nav TAG를 이용해서 clicked을 할때 HeroComponent로 이동할 수 있게 한다.
- routerLink attribute에 "/heroes"를 세팅
- Add a dashoard view
- Routing은 multiple views가 있을때 더 적합하다.
- CLI를 통해 DashboardComponent를 추가하자
- $ ng generate component dashboard
- DashboardComponent는 AppModule속에 선언이 된다.
- Add the dashboard route
- dashboard를 navigate하기 위해서는 router는 적절한 route가 필요하다.
- AppRoutingModule에 DashboardComponent를 import
- AppRoutingModule.routes를 추가하고, path에 dashboard, component에 DashboardComponent를 추가
- Add a default route
- app이 시작할때 browser의 주소는 web site's root를 가리키기 된다. 어떤 route에 매치되지 않으면 어디도 이동하지 않는다.
- app이 시작할때 자동으로 dashoard로 navigate하게 하기 위해서 AppRoutingModules.Routes array에 다음과 같이 추가
- path에는 '' redirectTo에는 "/dashboard", pathMatch에는 'full'
- Add dashboard link to the shell
- DashboardComponent와 HeroesComponent의 사이에서 앞,뒤로 이동을 할수도 있기 때문에 appComponent에 dashboard navigation 추가
- Navigating to hero details
- Delete hero details from Heroes Component
- Add a hero detail route
- : colon은 indicate :id
- DashboardComponent hero links
- HeroesComponent hero links
- Remove dead code
- Routable HeroDetailComponent
HTTP
- Angular's HTtpClient로 부터 data persistence features에 대해서 알아본다.
- HeroService에서 HTTPReqeusts를 통해 데이터를 가져온다.
- HTTP를 통해서 heroes를 추가, 삭제, 제거가 가능.
- Users는 heroes를 이름으로 검색이 가능
- Enable HTTP Services
- HttpClient는 HTTP를 통해서 remote server와 communicating을 위한 Angular's mechanism
- HttpClient는 app어디에서도 사용이 가능하다.
- root AppModule을 열고
- HttpClientModule을 import한다. (@angular/common/http)
- @NgModule.imports array에 추가
- Simulate a data server
- $ npm install angular-in-memory-web-api --save
- InMemoryWebApiModule과 InMemoryDataService를 import
- Heroes and HTTP
- HTTPClient, HttpHeaders를 @angular/common/http로 부터 import
- HttpClient를 prviate property http에 inject
- Get heroes with HttpClient
- 기존 of의 method를 this.http.get
- Http methods return one value
- HttpClient methods는 RxJS Observable을 return
- HttpClient.get returns response data
- 기본적으로 untyped JSON으로 응답이 온다.
- JSON 데이터의 모양은 서버의 데이터 API에 의해 결정, 이 예제에서는 hero data의 array로 반환
- Error handling
- catchError를 import (rxjs/operators)
- pipe method를 통해 에러를 핸들링 한다.
- Tap into the Observable
- tap을 통해 메시지의 로그를 출력할 수 있다.
- Get hero by id
- api/hero/:id를 통해 API를 제공할 수 있다.
- Update heroes
- save()를 통해 업데이트
- Add HeroService.updateHero()
- updateHero() method는 getHeroes()와 유사. 다른점은 http.put()을 사용한다는
- put은 URL, data, options
- Add a new hero
- input element를 사용해서
- Add HeroService.addHero9)
- put대신 post를 호.
- Delete a hero
- Add HeroService.deleteHero()
- HttpClient.delete 사용
- Search by name
- HeroService.searchHeroes
- Add search to the Dashboard
- Create HeroSearchComponent
- AsyncPipe
- Fix HeroSearchComponent class
- The serachTerms RxJS subject
- Chaining RxJS operators
반응형
'Programming > Web' 카테고리의 다른 글
[Node] Lazy loading module broken 문제 해결 방법 (0) | 2018.01.21 |
---|---|
[Angular] Data Binding (데이터 바인딩) (0) | 2018.01.21 |
[Angular] 01.튜토리얼(1~3) (0) | 2017.12.31 |
[Angular] 튜토리얼(Introduction, The Application Shell, The Hero Editor) (0) | 2017.12.21 |
[Angular] 시작하기 (0) | 2017.12.21 |