위의 튜토리얼은 https://angular.io/tutorial 을 참고하였습니다.
1) Display a Heroes List
이전까지는 하나의 hero 객체만 표현했었는데,
이 컴포넌트를 이용해서 여러개의 hero 객체들을 표현하려면 어떻게 해야 할까요?
1-1. Create mock heroes
일단 여러개의 hero 데이터가 있어야 합니다.
일반적으로는 다량의 데이터를 데이터 서버(ex, firebase)를 통해서 가져올 것이나, 일단은 임시 데이터를 만들어서 사용해봅시다.
// mock-heroes.ts
import {Hero} from './hero';
export const HEROES: Hero[] = [
{ id: 11, name: 'Mr. Nice' },
{ id: 12, name: 'Narco' },
{ id: 13, name: 'Bombasto' },
{ id: 14, name: 'Celeritas' },
{ id: 15, name: 'Magneta' },
{ id: 16, name: 'RubberMan' },
{ id: 17, name: 'Dynama' },
{ id: 18, name: 'Dr IQ' },
{ id: 19, name: 'Magma' },
{ id: 20, name: 'Tornado' }
];
-
Hero 클래스를 임포트
-
임포트한 Hero 클래스를 이용한 배열을 만듬
=> 이 배열을 임포트해서 컴포넌트에서 사용해보자.
1-2. Displaying heroes
- 컴포넌트 ts 파일에서 Hero 객체의 배열들을 임포트하자.
- 임포트 한 뒤에 변수를 배열로 바꾸자.
- 배열의 원소들을 for문처럼 표현하기 위해 *ngFor directives를 이용하자.
import { Component, OnInit } from '@angular/core';
import { HEROES } from '../mock-heroes';
//생략..
export class HeroesComponent implements OnInit {
heroes = HEROES;
//생략...
}
<h2>히어로들</h2>
<ul>
<li *ngFor="let hero of heroes">
<div>이름 : {{hero.name}}</div>
<div>번호 : {{hero.id}}</div>
</li>
</ul>
*ngFor
이라는 directive를 통해서 for문을 표현할 수 있습니다.
그러면, 각 li태그의 자식태그들은 hero라는 값을 사용할 수 있습니다.
참고로 *
를 붙이는게 문법적으로 매우 중요하다고 하니 꼭 기억하도록 합시다.
1-3. Style the heroes
스타일링은 css파일을 통해서 하면 되는데,
특정 컴포넌트에 대한 디자인은 각각의 css파일에서 하는 것을 추천합니다.
그래야 재사용성을 높일 수 있기 때문입니다.
이런 각각의 css파일들을 잘 만들고 난 뒤에는,
@Component({
selector: 'app-heroes',
templateUrl: './heroes.component.html',
styleUrls: ['./heroes.component.css']
})
여기 보이는 styleUrls 배열을 통해서 파일을 적어주면 독립적으로 잘 사용할 수 있습니다.
2) Detail page
원하는 기능
- 유저가 히어로들의 list를 클릭 => 각 히어로의 디테일을 표시
필요한 요소
- 각 히어로 아이템을 클릭하는 이벤트를 감지
- 히어로의 디테일 파일을 업데이트
2-1. Add a click event binding
<h2>히어로들</h2>
<ul>
<li *ngFor="let hero of heroes" (click)="onSelect(hero)">
<div>이름 : {{hero.name}}</div>
<div>번호 : {{hero.id}}</div>
</li>
</ul>
이벤트를 바인딩하는 것은 ( event 이름 )="함수"
와 같은 문법인데,
특정 이벤트를 실행하면 함수(method)를 실행한다는 뜻입니다.
앵귤러에서는 이 함수를 event handler라고 부릅니다.
아.. 그러고보니 타입스크립트에서 method는 어떻게 선언하나요? 알아보도록 합시다.
2-2. Add the click event handler
export class HeroesComponent implements OnInit {
heroes = HEROES;
selectedHero: Hero;
onSelect(hero: Hero): void {
this.selectedHero = hero;
}
}
역시 typescript의 문법은 자바스크립트와 비슷한 점이 많습니다.
selectedHero: Hero
는 마치 자바스크립트의 선언 문법과 비슷해보이구요.
onSelect(hero: Hero): void {
this.selectedHero = hero;
}
이부분은 오히려 자바의 메서드를 선언하는 부분과 비슷하네요.
아무튼 히어로를 클릭할 때 마다 this.selectedHero
가 바뀌면서 그에 대한 정보를 표현해주는 것으로 보입니다.
2-3. Update the details template
그러면 이제 selectedHero를 이용해서 정보를 표현하는 태그들을 더 만들어봅시다.
<h2>{{selectedHero.name | uppercase}} Details</h2>
<div><span>id: </span>{{selectedHero.id}}</div>
<div>
<label>name:
<input [(ngModel)]="selectedHero.name" placeholder="name" />
</label>
</div>
그런데..
요런 에러메시지가 뜨는데, 당연합니다. 처음에는 아무것도 클릭하지 않았으니
this.selectedHero
는 undefined이고, 이녀석은 아무런 프로퍼티도 없으므로 name에 접근하면 큰 오류가 나는겁니다.
해결방법은 selectedHero가 없는 값이라면 아예 selectedHero를 사용하는 태그를 표시하지 않는 것입니다.
2-4. The fix - hide empty details with *ngif
ngif 조건문을 통해서 할 수 있습니다!
<div *ngIf="selectedHero">
<!-- 아까 추가했던 내용 -->
</div>
정상적으로 잘 작동하며, 심지어 에러도 없습니다. 왜냐하면 조건문이 false일 때 DOM에서 아예 히어로 디테일을 제거하기 때문입니다. vue.js의 v-if 디렉티브와 동일합니다.
2-5. Style the selected Hero
angular는 style class binding을 vue에 비해서 쉽게 할 수 있습니다.
[class.(css 클래스 이름)] = "조건문"
의 문법을 통해서 클래스를 추가할지 말지를 설정할 수 있는데요. 예를 들어,
[class.selected] = "selectedHero === hero"
라고 하면 hero객체와 selectedHero객체를 비교해서 값이 똑같다면 이 태그에 selected값이 생깁니다.
그것을 이용해서 css를 편집해봅시다.
<h2>히어로들</h2>
<ul>
<li class="hero-list"
*ngFor="let hero of heroes"
[class.selected]="hero === selectedHero"
(click)="onSelect(hero)">
<div>이름 : {{hero.name}}</div>
<div>번호 : {{hero.id}}</div>
</li>
</ul>
.selected {
border : 1px solid #181818;
}