AngularJS/AngularJS

▶ [Angular2 Tutorial] 4. Multiple Component

비주얼라이즈 2016. 9. 10. 22:23

▶ [Angular2 Tutorial] 4. Multiple Component


이 글에서는 angular2 공식페이지의 튜토리얼 중 Multiple Components 에 대한 내용을 정리해보려고한다. 이것은 앞서 정리했던 튜토리얼 3 - Master/detail 에 이어서 진행된다. 이 글의 작업 환경 및 이전까지의 코드에 대한 설명이 궁금하다면, AngularJS2 - Tutorial 페이지를 참고하는 것을 추천한다.




(튜토리얼3. Master/Detail에 이어) 우리의 app은 발전하고 있다. 


본격적으로 내용을 살피기에앞서 다음과 같은 디렉토리 구조를 확인하고, 지금현재 이와 다른 경우라면 이전 글에서 예시내용과 다른 부분에 대해서 다시 탐색해보도록한다.


[ 사진 : angular2 공식홈페이지, tutorial - multiple components ]





Keep the app transpiling and running


이전과 마찬가지로, 우리는 TypeScript와 TypeScript Compiler를 사용할 것이다. 이것은 우리가 코드 작성을 변경할 때, 변경을 감지하고 우리의 서버에 반영한다. (위 사진에서 설명한 디렉토리 구조를 준비했다면) 다음 코드를 실행한다.


npm start

이렇게 한번 실행해두면, 우리가 예제 콘텐츠인 "Tour of Heroes"라는 콘텐츠를 빌드하는 동안 기능이 유지된다.





Making a Hero Detail Component


우리의 heroes list 와 우리의 hero details 는 같은 파일 내 같은 Component에 있다. 이 코드들이 지금은 매우 작은 수준이지만, 개발을 해나가다보면 점점 덩치가 커지게된다. 


슬프지만 우리는 개발과정에서 하나이상의 요구사항을 받을 것이 확실하다. 그러나 모든 변화는, 딱히 내세울 만한 어떠한 이득도 없이 두 Component를 모두 위험 영역에 두고 실험하고 있다.






Separating the Hero Detail Component


app 폴더에 hero-detail.component.ts 라는 새로운 파일을 추가한다. 그리고 HeroDetailComponent 를  다음과 같이 생성한다.



import { Component, Input }  from '@angular/core';

@Component({
selector: 'my-hero-detail',
})
export class HeroDetail Component{
}




import { Component, Input } from '@angular/core';

우리는 맨 첫줄에서, (곧이어 사용하기위해) Component Input Decorator들을 Angular에서 가져온다.




@Component({
    selector:'my-hero-detail';
})
export class HeroDetail Component{
}

이어서 우리는 @Component Decorator로서, 요소를 식별할 셀렉터(selector) 이름을 지정하고, 메타 데이터를 생성한다. 여기까지 잘 마쳤다면 우리는 이것을 AppComponentimport해준다. 그리고나서  <my-hero-detail>에 부합하는 요소를 생성해준다.





Hero Detail Template



여기까지 마친 순간, HeroesHero의 상세보기가 AppComponent에서 하나의 템플릿으로 결합된다. 









Cut & Paste


우리는 여기서 Hero Detail 콘텐츠를 AppContent 에서 잘래내고(cut) 새로운 템플릿의 HeroDetailComponent라는 속성에 붙어넣기(paste)한다.


이전에 우리는 selectedHero.name 속성을  AppComponent 의 속성에 바인딩했었다. 

우리의 HeroDetailComponent는 selectedHero 라는 속성이 아닌, hero 라는 속성을 가지고 있다.


따라서 우리는 우리의 모든 template 에서 selectedHero hero로 교체한다.

(모든 교체를 완료했다면) 결과 형태는 다음과 같은 것이다.



app/hero-detail.component.ts(template)


template: `
    <div *ngIf="hero">
<h2>{{hero.name}} details! </h2>
<div><label>id:</label>{{hero.id}}</div>
<div>
<label> name:</label>
<input [(ngModel)]="hero.name" placeholder="name"/>
</div>
    </div>


이제 우리의 hero detail 레이아웃은 오로지 'HeroDetailComponent'에만 존재한다.




Add the hero property

여기서부터는 우리가 'Component class'라 말하는 'hero'property를 추가하는 방법에 대해서 살펴보려고 한다.



app/hero.ts

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



우리는 Hero 클래스를 hero.ts로 부터  추출(export)한다. 왜냐하면 우리는 모든 Component의 파일을 참조해야하기 때문이다. 'app.component.ts''hero-detail.componet.ts'모두의 상단에 다음 'import' 문을 추가해준다.



import { Hero } from './hero';




The hero property is an input


HeroDetail Component 는 화면에 표현할 영웅에 대해서 이야기해야한다. 누가 말할 것인가? 바로 parent인 AppComponent이다.!

AppComponent 는 어느 hero를 화면에 표현해야할지 알고있다 : 사용자가 Hero list에서 선택한 hero . 사용자의 선택은 selectedHero 의 속성이다.


우리는 AppComponent의 템플릿을 업데이트해야하는데, 이는 이것의 selectedHero 속성을 우리의 HeroDetailComponent 의 속성에 바인딩하기 위해서다. 바인딩은 다음 코드와 같은 형태로 하게된다.



<my-hero-detail [hero]="selectedHero"></my-hero-detail>


주의 hero 속성은 등호(=)의 왼쪽에, 대괄호(square brackets)안에 넣는다. 


Angular는 우리가 Input 속성이 될 수 있는 target 속성을 선언할 것을 주장한다. 만약 우리가 그렇게 하지 않으면, Angular는 바인딩을 거부하고 에러발생을 알린다. Angular 측에서 input 속성을 어떻게 다루고 있는지 보다 자세한 내용을 알고 싶다면 여기를 클릭해 확인해 보자.


여기에 heroinput으로 선언하는 몇 가지 방법이 있다. 따라서, 각자 선호하는 방법으로 진행하면된다. 나는 일단  angular2 튜토리에얼에서 제공하고있는 방법을 그대로 따라가본다.




@Input()
hero : Hero;


@Input() 에 대해서도 마찬가지로, 보다 확실하게 알고싶다면 angular에서 정리한 페이지를 확인하자.





Refresh the AppComponent

다시 AppComponent 로 돌아가서 HeroDetailComponent. 를 사용하는 방법에 대해 살펴본다. 


시작은, 우리가 참조(Refer)하기위해 HeroDetailComponentimport 하는 것부터 한다.




import { HeroDetailComponent } from './hero-detail.component';


우리는 템플릿 안에서 삭제된 HeroDetail Content 내용을 찾은 뒤, HeroDetailComponent를 표현하는 요소 태그를 추가한다.[각주:1]


<my-hero-detail> </my-hero-detail>

my-hero-detailHeroDetailComponent 메타데이터의 선택자로 설정한 이름이다.


우리가 AppComponentselectedHero 속성을 HeroDetailComponent 요소의 hero 속성에 바인딩할 때 까지 두 Component가 조정되지 않았다.  이렇게 말이다.



<my-hero-detail [hero]="selectedhero"></my-hero-detail>

AppComponent의 템플릿의 구조는 이렇게 되어있을 것이다.


app.component.ts (template)


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>
  <my-hero-detail [hero]="selectedHero"></my-hero-detail>
`,


바인딩 덕분에, HeroDetailComponentAppComponent로부터 hero를 받아야한다. 그리고 hero list의 밑에 받아온 hero를 표시해야한다. 세부사항(detail)은 사용자가 새로운 hero를 선택하는 모든 순간에도 업데이트를 해야한다




It's not happening yet!


hero 의 사이를 클릭해보자. 상세정보(detail)가 없다. 우리는 에러가 나왔을까 콘솔창을 확인해보지만, 에러도 없다. 

이것은 Angular가 new tag 를 무시하기때문이다.






The directives array


브라우저는 HTML tag, 그리고 속성을 무시하게된다. 그래서 Angular를 사용한다. 우리는 HeroDetailComponent 를 import 했고, 이것을 template 안에서 사용했다. 그러나 우리는 Angular에게 이것에 대해 말하지 않았다.


우리는 메타데이터 지시어 배열(metadata direcvies array)을 나열하여 Angular에게 말한다. templatestyle 속성 바로 다음, array 속성을 @Componentconfiguration 객체 아래에 추가한다.


app/app.component.ts (Directives)

directives:[HeroDetailComponent]




It works!


이제 브라우저의 화면을 확인해보면 hero 의 리스트를 볼 수 있다. 또한, 우리가 hero 를 선택하면 선택한 hero 의 세부정보를 볼 수 있다. 이전과 근본적으로 다른점이 있다면, 우리가 이제 HeroDetailComponent 를 app의 어디서나 사용할 수 있고 그 결과를 볼 수 있다는 것이다.



여기까지의 코드실행에서 어려움이 있었다면 다음 내용을 참고하자.


- 디렉터리 구조

- (이번 튜토리얼에서 추가된 각 파일 별 코드내용)



디렉터리 구조


[ Angular 공식 홈페이지 튜토리얼 4 진행후,  디렉터리 모습 ]


그 다음에 각 파일별 코드내용은? 

- 코드펜?




  1. Find the location in the template where we removed the Hero Detail content and add an element tag that represents the HeroDetailComponent. [본문으로]