티스토리 뷰

오늘은 어떤걸 포스팅할까 하다가 오랜만에 Angular 2를 진행해봅니다.
이번에도 역시나 npm start로 서버 띄어놓고 시작합니다.

우선 파일 제일 아래에 배열을 추가합니다. TypeScript에서도 기본적인 JavaScript 문법은 동작을 합니다.
var 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" }
];
 

그런 다음 AppComponent 클래스 안에 변수 하나를 선언하고 위의 배열을 assign 해줍니다.
export class AppComponent {
    public heroes = HEROES;
    title = 'Tour of Heroes';
    hero: Hero = {
        id: 1,
        name: 'windstorm'
    };
}
 

그리고는 이 배열을 화면에 뿌려봅시다. 반복문하면 for문이죠? Angular 2에서는 ngFor라는 Directive가 존재합니다. template 코드를 아래와 같이 수정해줍시다.
<h1>{{title}}</h1>
      <h2>My Heroes</h2>
      <ul class="heroes">
        <li *ngFor="let hero of heroes">
            <span class="badge">{{hero.id}}</span> {{hero.name}}
        </li>
      </ul>
      <h2>{{hero.name}} details!</h2>
      <div><label>id: </label>{{hero.id}}</div>
      <div>
        <label>name: </label>
        <input [(ngModel)]="hero.name" placeholder="name">
      </div>
     
     . 화면을 띄어보면 <li> 태그가 반복되는것을 볼 수 있습니다. (이전 버전에서는 let hero 대신 var hero 였는데 최근 업데이트 되면서 바뀌었네요.)
     . 문법은 *ngFor="let 사용할변수 of 클래스내배열변수" 입니다. (*은 반드시 써주셔야 합니다.)
     . 나머지는 Data Binding에서 배운대로 {{}}안에 변수를 넣어주면 됩니다.

처음에는 조금 어색할 수 있겠지만 정말 쉽습니다. 아주 간단하게 태그를 반복할 수가 있었습니다. 그럼 template에 이어 다른 component 속성인 styles을 볼까요? template 코드 뒤에 콤마(,)를 넣고 아래와 같이 styles를 지정해줍니다.
styles:[`
      .selected {
        background-color: #CFD8DC !important;
        color: white;
      }
      .heroes {
        margin: 0 0 2em 0;
        list-style-type: none;
        padding: 0;
        width: 15em;
      }
      .heroes li {
        cursor: pointer;
        position: relative;
        left: 0;
        background-color: #EEE;
        margin: .5em;
        padding: .3em 0;
        height: 1.6em;
        border-radius: 4px;
      }
      .heroes li.selected:hover {
        background-color: #BBD8DC !important;
        color: white;
      }
      .heroes li:hover {
        color: #607D8B;
        background-color: #DDD;
        left: .1em;
      }
      .heroes .text {
        position: relative;
        top: -3px;
      }
      .heroes .badge {
        display: inline-block;
        font-size:10pt;
        color: white;
        padding: 0.8em 0.7em 0 0.7em;
        background-color: #607D8B;
        line-height: 1em;
        position: relative;
        left: -1px;
        top: -4px;
        height: 1.8em;
        margin-right: .8em;
        border-radius: 4px 0 0 4px;
      }
    `]
 
     . styles도 마찬가지로 여러줄로 할때는 `` 사이에 넣어줍니다. (참고로 ``는 ECMAScript6에 정의되어 있는 정식 스펙입니다.)
     . styles는 template과는 다르게 반드시 [] 사이에 넣어서 배열로 만들어 줘야 합니다.

이번에는 이벤트를 걸어보겠습니다. 아까 만든 <li> 태그를 아래와 같이 수정합니다.
<li *ngFor="let hero of heroes" (click)="onSelect(hero)">
  <span class="badge">{{hero.id}}</span> {{hero.name}}
</li>
 
     . 이벤트를 선언할때는 () 괄호 안에 이벤트명을 넣습니다. (이벤트명)="함수명(변수)" 로 작성하면 됩니다.
     . 여기서 () 괄호는 Event Binding이라고 합니다.

위에서 onSelect 함수를 사용했는데 함수를 아직 안만들었죠? 함수는 다시 AppComponent 클래스로 돌아와서 만들어 줍니다.
export class AppComponent {
    public heroes = HEROES;
    selectedHero: Hero;
    title = 'Tour of Heroes';

    onSelect(hero: Hero) { this.selectedHero = hero; }
}
 
     . 선택된 Hero를 담아줄 변수를 만들었습니다. 기존의 hero 변수를 대신해줍니다.
     . onSelect 함수는 hero 파라미터를 갖는 함수입니다.(만약 onSelect 함수가 string을 리턴하면 onSelect: string(hero: Hero) 로 하면 됩니다.)
     . 주의하실 사항은 항상 클래스 변수 혹은 함수를 사용할 때는 this를 붙여줘야만 합니다. 생략하시면 안됩니다.

hero 변수 대신 selectedHero 변수가 생겼으니 template 부분도 수정을 해줘야겠죠?
<h1>{{title}}</h1>
      <h2>My Heroes</h2>
      <ul class="heroes">
        <li *ngFor="let hero of heroes">
            <span class="badge">{{hero.id}}</span> {{hero.name}}
        </li>
      </ul>
      <h2>{{selectedHero.name}} details!</h2>
      <div><label>id: </label>{{selectedHero.id}}</div>
      <div>
          <label>name: </label>
          <input [(ngModel)]="selectedHero.name" placeholder="name"/>
      </div>
     
     . 기존 소스와 동일합니다. hero 대신 selectedHero로 바꿔주기만 했습니다.
     . 지금은 Hero 리스트에서 하나를 클릭하면 selectedHero가 클릭한 Hero로 변경되면서 Detail의 정보가 바뀔거라고 예상이 됩니다.

하지만 화면에는 아무것도 안뜹니다. console 창을 확인하면 오류가 나타납니다. 이것은 selectedHero가 최초 undefined 되었기 때문에 나타나는 오류입니다.
이를 해결하기 위한 방법은 2가지 입니다. 하나는 선언과 동시에 값을 하나 지정해준다. 다른 하나는 *ngIf를 사용한다 입니다. 값을 지정해주는 건 너무 쉬우니깐 *ngIf에 대해 알아봅시다.
<div *ngIf="selectedHero">
          <h2>{{selectedHero.name}} details!</h2>
          <div><label>id: </label>{{selectedHero.id}}</div>
          <div>
              <label>name: </label>
              <input [(ngModel)]="selectedHero.name" placeholder="name"/>
          </div>
      </div>
     
     . HeroDetail 부분을 <div> 태그로 감싸는데 *ngIf="selectedHero" 라는 속성을 추가했습니다. 만약 selectedHero가 있으면, 이 태그를 만들겠다는 것입니다.
     . 만약 selectedHero가 없다? 그러면 <div> 태그가 없어지고 그로 인해 <div> 태그 하위에 있는 것들도 없습니다. 따라서 selectedHero.name을 연산할 일이 없기 때문에 에러가 발생하지 않습니다.

위에서 배운 *ngFor과 *ngIf는 구조적 프로그래밍에 사용되는 것들로 structural directive라고 합니다.
마지막으로 선택된 Hero에 style을 추가해보겠습니다. <li> 태그에 아래의 속성을 추가해줍니다.
[class.selected]="hero === selectedHero"
     . 위의 styles에 selected 클래스는 배경 색깔을 변경하고, 글자색을 바꿔줍니다.
     . 문법은 [class.클래스명]="조건문" 입니다. 조건에 맞을 경우 클래스가 추가되는 형식입니다. (여기서 클래스는 스타일의 클래스입니다.)

여기서 확인을 해보면 Hero 선택 시, 선택한 Hero의 색깔이 변경되고, 아래 Hero Detail 부분이 바뀌는 것을 볼 수 있습니다. 이것을 순수 JS + jQuery로 작성을 한다고 생각해봅시다.
생각만 해도 복잡하죠? 아래에 full app.component.ts 코드가 있습니다. 보시면 아시겠지만 엄청나게 직관적입니다. 이 태그는 반복이야, 이 태그는 어떠한 조건일 때만 나타나 등등 참 쉽습니다.
이번 포스팅도 너무 날로 먹었나요?ㅎㅎ https://angular.io 공식 홈페이지 코드를 그대로 참조했습니다. 다들 즐코딩 되세요:)
import { Component } from '@angular/core';

export class Hero {
  id: number;
  name: string;
}

@Component({
  selector: 'my-app',
  template:`
    <h1>{{title}}</h1>
    <h2>My Heroes</h2>
    <ul class="heroes">
      <li *ngFor="let hero of heroes"
        [class.selected]="hero === selectedHero"
        (click)="onSelect(hero)">
        <span class="badge">{{hero.id}}</span> {{hero.name}}
      </li>
    </ul>
    <div *ngIf="selectedHero">
      <h2>{{selectedHero.name}} details!</h2>
      <div><label>id: </label>{{selectedHero.id}}</div>
      <div>
        <label>name: </label>
        <input [(ngModel)]="selectedHero.name" placeholder="name"/>
      </div>
    </div>
  `,
  styles:[`
    .selected {
      background-color: #CFD8DC !important;
      color: white;
    }
    .heroes {
      margin: 0 0 2em 0;
      list-style-type: none;
      padding: 0;
      width: 15em;
    }
    .heroes li {
      cursor: pointer;
      position: relative;
      left: 0;
      background-color: #EEE;
      margin: .5em;
      padding: .3em 0;
      height: 1.6em;
      border-radius: 4px;
    }
    .heroes li.selected:hover {
      background-color: #BBD8DC !important;
      color: white;
    }
    .heroes li:hover {
      color: #607D8B;
      background-color: #DDD;
      left: .1em;
    }
    .heroes .text {
      position: relative;
      top: -3px;
    }
    .heroes .badge {
      display: inline-block;
      font-size:10pt;
      color: white;
      padding: 0.8em 0.7em 0 0.7em;
      background-color: #607D8B;
      line-height: 1em;
      position: relative;
      left: -1px;
      top: -4px;
      height: 1.8em;
      margin-right: .8em;
      border-radius: 4px 0 0 4px;
    }
  `]
})
export class AppComponent {
  title = 'Tour of Heroes';
  heroes = HEROES;
  selectedHero: Hero;

  onSelect(hero: Hero) { this.selectedHero = hero; }
}

var 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" }
];

'Javascript > Angular' 카테고리의 다른 글

5-1. Routing 기초 - 1  (0) 2016.06.19
4. Service 만들기  (0) 2016.06.17
3. 파일 나누기, Component 나누기  (1) 2016.06.15
1. Data Binding 맛보기  (0) 2016.06.09
0. Angular 2 시작하기  (0) 2016.06.05
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함