HTML52017.03.02 22:20


https://angular.io/docs/ts/latest/guide/router.html


라우트에 파라메터 적용하기


이전 예제에서 정의한 라우트정의를 다시 보자


{ path: 'hero/:id', component: HeroDetailComponent }


:id는 path에서 라우트파라메터의 슬롯을 생성한다. 이 경우 라우터는 이 슬롯에 hero의 id를 삽입한다.


heroid 15번의 상세화면으로 이동하고자 한다면 아래와 같이 접근하면 된다.


localhost:3000/hero/15



다음은 hero list를 표시하는 템플릿이다.


template: `

  <h2>HEROES</h2>

  <ul class="items">

    <li *ngFor="let hero of heroes | async"

      (click)="onSelect(hero)">

      <span class="badge">{{ hero.id }}</span> {{ hero.name }}

    </li>

  </ul>


  <button routerLink="/sidekicks">Go to sidekicks</button>

`


그리고 hero를 클릭했을 때 호출된 함수는 아래와 같다.


  onSelect(hero: Hero) {

    this.router.navigate(['/hero', hero.id]);

  }


this.router를 사용하기 위해서는 생성자에서 Router를 inject해야 한다.


constructor(

  private router: Router,

  private service: HeroService

) {}


위와 같이 하면 Hero를 선택하면 HeroDetailComponent에 id값이 파라메터로 전달된다. 코드를 보면 알겠지만 파라메터는  배열로 전달된다.

HeroDetailComponent에서는 id값에 어떻게 접근할 수 있을까?

ActivatedRoute서비스로 가능하다.

ActivatedRoute : 라우팅정보를 위한 원스탑서비스이다.
라우팅서비스에서 얻어지는 ActivatedRoute는 다음과 같은 정보를 제공한다.

url: 라우트된  path의 obserserable로 라우트경로의 배열료 구성된다.
data : 라두트에서 제공되는 데이터 객체를 포함하는 observerable
params : 옵셔널파라메터
queryParams : 모든 라우트에서 유효한 query parameter
fragment : 모들 라우트에서 유효한 URL fragment
outlet : 라우트를 렌더할때 사용되는 RouterOutlet
routeConfig : origin path를 포함하는 라우트에 사용되는 설정정보
parent : 자식 라우트의 경우 부모의 ActivatedRoute
firstChild : 자식 라우트가 있을 경우 첫번째 ACtivatedRoute
children : 현재 라우트 이하 모든 라우트들

다음과 같이 Router, ActivatedRoute, Params를 import 해야 한다.

import { Router, ActivatedRoute, Params } from '@angular/router';

switchMap연산자를 import하면 Observerable 라우트 파라메터들을 처리할 수 있다.

import 'rxjs/add/operator/switchMap';

해당 모듈을 사용하기 위해 inject를 구현한다.

constructor(
  private route: ActivatedRoute,
  private router: Router,
  private service: HeroService
) {}

이 후 ngOnInit에서 ActivatedRoute서비스를 통해서 파라메터에 접근이 가능하다.

ngOnInit() {
  this.route.params
    // (+) converts string 'id' to a number
    .switchMap((params: Params) => this.service.getHero(+params['id']))
    .subscribe((hero: Hero) => this.hero = hero);
}

파라메터가 Observerable로 제공되기 때문에 switchMap연산자를 id파라메터를 이름으로 접근하여 HeroService에 전달이 가능하다.
subscribe메서드로 id가 변경되면 감지해서 Hero 정보를 다시 셋할 수 있다.
이렇게 하면 id정보의 변경을 감지하여 화면은 유지한체 정보를 업데이트 할 수 있다.
shapshot의 경우는 non-observerable로 무조건 list에서만 detail로 진입한다면 사용이 가능하다.

ngOnInit() {
  // (+) converts string 'id' to a number
  let id = +this.route.snapshot.params['id'];

  this.service.getHero(id)
    .then((hero: Hero) => this.hero = hero);
}





신고
Posted by 삼스
HTML52017.03.02 21:49


다음으로는 세가지에 대해 알아보겠다.

  • App과 route들을 module을 사용해서 feature 영역에 배치하기
  • 콤포넌트에서 다른 콤포넌트로 네이게이트하기
  • 필수 또는 옵셔널한 정보를 라우트파라메터로 전달하기

대부분의 앱을 개발하다보면 업무별로 구분하기 위해서 폴더들을 생성하여 그 아래에 소스들을 배치하게 된다.

src/app/heroes |- hero-detail.component.ts |- hero-list.component.ts |- hero.service.ts |- heroes.module.ts


heros.module.ts는 아래와 같이 정의되어 있다.


import { NgModule }       from '@angular/core';
import { CommonModule }   from '@angular/common';
import { FormsModule }    from '@angular/forms';
import { HeroListComponent }    from './hero-list.component';
import { HeroDetailComponent }  from './hero-detail.component';
import { HeroService } from './hero.service';
@NgModule({
  imports: [
    CommonModule,
    FormsModule,
  ],
  declarations: [
    HeroListComponent,
    HeroDetailComponent
  ],
  providers: [ HeroService ]
})
export class HeroesModule {}


heros feature에는 두개의 콤포넌트가 있다. herolist와 herodetail. 리스트뷰는 조회된 결과를 표시하고 detail은 선택된 hero의 상세정보를 표시한다. list에서 detail로 넘어갈때는  hero id를 넘겨야 한다.


다음은 라우트 설정이다.


src/app/heroes/heroes-routing.module.ts

import { NgModule }             from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { HeroListComponent }    from './hero-list.component';
import { HeroDetailComponent }  from './hero-detail.component';
const heroesRoutes: Routes = [
  { path: 'heroes',  component: HeroListComponent },
  { path: 'hero/:id', component: HeroDetailComponent }
];
@NgModule({
  imports: [
    RouterModule.forChild(heroesRoutes)
  ],
  exports: [
    RouterModule
  ]
})
export class HeroRoutingModule { }


두개의 콤포넌트에 대한 라우팅설정을 완료하였다. 하나는 path에 파라메터를 전달할 수 있도록 정의하였다. 그리고 HeroRoutingModule을 export하였다.

그리고 RouterModule에 등록하고 있는데  AppRoutingModule과 다른점은 forRoot가 아니라 forChild를 사용한것이다. feature 모듈에서는 forChild를 사용해야 한다. forRoot는 앱레벨이다.

이제 HerosModule에 추가해야 한다.


import { NgModule }       from '@angular/core';
import { CommonModule }   from '@angular/common';
import { FormsModule }    from '@angular/forms';
import { HeroListComponent }    from './hero-list.component';
import { HeroDetailComponent }  from './hero-detail.component';
import { HeroService } from './hero.service';
import { HeroRoutingModule } from './heroes-routing.module';
@NgModule({
  imports: [
    CommonModule,
    FormsModule,
    HeroRoutingModule
  ],
  declarations: [
    HeroListComponent,
    HeroDetailComponent
  ],
  providers: [ HeroService ]
})
export class HeroesModule {}

앱 메인라우터 설정과 중복이 있더라도 feature 라우터 우선으로 동작하는데는 문제가 없으나 중복은 좋지 않기 때문에 메인 라우터에 중복이 있다면 제거한다.


import { NgModule }              from '@angular/core';
import { RouterModule, Routes }  from '@angular/router';

import { CrisisListComponent }   from './crisis-list.component';
// import { HeroListComponent }  from './hero-list.component';  // <-- delete this line
import { PageNotFoundComponent } from './not-found.component';

const appRoutes: Routes = [
  { path: 'crisis-center', component: CrisisListComponent },
  // { path: 'heroes',     component: HeroListComponent }, // <-- delete this line
  { path: '',   redirectTo: '/heroes', pathMatch: 'full' },
  { path: '**', component: PageNotFoundComponent }
];

@NgModule({
  imports: [
    RouterModule.forRoot(appRoutes)
  ],
  exports: [
    RouterModule
  ]
})
export class AppRoutingModule {}


HorosModule로 별도로 분리된 모듈의 경우 AppModule에 추가해주어야 한다.

app.module.ts에 imports에 추가해준다.

app.module.ts에 import되는 순서에 따라 라우팅시 패턴매칭의 순서가 정해진다. 원하는대로 동작시키길 원한다면 순서에 유의해야 한다.



신고
Posted by 삼스
HTML52017.03.02 20:41


Angular routing & navigation


한뷰에서 다른 뷰로 넘어갈수 있도록 해준다.


개요


브라우저의 네비게이션모델은 다음과 같다.

- 주소바에 주소를 입력하면 해당 페이지로 이동한다.

- 페이지내의 링크를 누르면 해당 페이지로 이동한다.

- 뒤로가기/앞으로가기 버튼을 누르면 히스토리상의 앞/뒤 페이지로 이동한다.


앵귤러라우터는 이 모델을 빌어서 구현되었다. URL주소를 분석하여 클라이언트뷰 네비게이션 명령을 수행한다. 추가 파라메터를 전달하여 해당 페이지의 콘텐츠를 멀 표시할지 결정하는데 도움을 줄수 있다. 

라우터를 페이지에 링크할 수 있고 사용자가 클릭하면 해당 뷰로 네비게이트 할것이다. 


<base href>

대개의 라우팅애플리케이션은 index.html에 <head>내에 첫번째로 <base>엘리먼트를 추가한다. 이 값은 라우터가 네비게이션 url을 어떻게 조합할지 결정한다.


<baser href="/">


라우터는 옵셔널 서비스로 앵귤러 기본 콤포넌트는 아니다 따라서 아래와 같이 추가해주어야 한다.


import { RouterModule, Routes } from '@angular/router';


설정하기


라우팅 앵귤러 앱은 하나의 싱글톤 Router 서비스를 갖는다. 브라우저 URL이 변경되면 해당 표시할 콤포넌트를 결정하기 위해 해당 Route를 찾는다.

Router는 설정해주기전에는 Route를 갖지 않는다. 아래 예는 4개의 route를 설정, RouterModule.forRoot메소드롤 설정하고 AppModule의 imports 배열에 추가한다.


const appRoutes: Routes = [

  { path: 'crisis-center', component: CrisisListComponent },

  { path: 'hero/:id',      component: HeroDetailComponent },

  {

    path: 'heroes',

    component: HeroListComponent,

    data: { title: 'Heroes List' }

  },

  { path: '',

    redirectTo: '/heroes',

    pathMatch: 'full'

  },

  { path: '**', component: PageNotFoundComponent }

];


@NgModule({

  imports: [

    RouterModule.forRoot(appRoutes)

    // other imports here

  ],

  ...

})

export class AppModule { }


appRoutes는 라우팅방법에 대해 기술한다. 그리고 imports에 RouterModule.forRoot네 파라메터로 넘기게 된다.


각 Route는 하나의 콤포넌트에 URL path하나를 맵핑한다. path는 '/'로 시작하지 않는다. 뷰간의 네비게이션시 상대적/절대적 경로를 만드는데 사용된다.


:id는 route파라메터의 토큰으로 /hero/42같은 URL에서 42가 id 파라메터에 해당하게 된다. HeroDetailComponent는  hero정보를 표시하기 위해 id값을 취해서 정보를 표시한다.


data 속성은 해당 route와 연관된 데이터를 위치시키는데 사용된다. 활성화된 각 route에서 접근이 가능하다. 페이지타이틀이나 로그텍스트(방문페이지표시), 또는 읽기전용의 스테틱데이터를 저장하는데 사용하는게 권장된다.


빈 path의 경우 URL이 빈경우에 해당하며 일반적으로 시작화면이 된다. 위 예의 경우 디폴트 라우드는 /heros URL로 redirect되고 HeroListComponent가 표시되게 된다.


** path는 와일드카드로 라우터는 요청된 URL이 매칭되는 경로가 없는 경우 표시된다. 404-Not Found에 대해 특정 페이지로 이동시켜서 변경이 가능하다.


route설정의 순서는 라우터가 매칭되면 이 후의 것들은 무시가 되기 때문에 전략적으로 설정해야 한다.



Router outlet

Router설정에 따라서 표시할 콤포넌트가 결정되면 해당 내용은 RouterOutlet에 표시된다.


<router-outlet></router-outlet>



Router links

라우팅된 페이지가 표시된 후 다른 페이지로 이동은 어떻게 할까? 브라우저 주소바에 URL을 입력하여 이동이 가능하나 대부분 페이지내에서 클릭을 통해서 이동하게 된다.


template: `

  <h1>Angular Router</h1>

  <nav>

    <a routerLink="/crisis-center" routerLinkActive="active">Crisis Center</a>

    <a routerLink="/heroes" routerLinkActive="active">Heroes</a>

  </nav>

  <router-outlet></router-outlet>

`


anchore 태그의 RouterLink 디렉티브는 라우팅을 제어할 수 있게 해준다. URL은 미리 결정되기 때문에 하드코딩으로 routerLink를 지정할 수 있다.


RouterLinkActive 디렉티브는 현재 선택된 라우터를 구별할 수 있게 해준다. active CSS 클랙스가 액티브 되었을 때 사용되게 된다.



Router state

네이게이션 라이프사이클이 완료된 후에 라우터는 현재 상태를 반영하는 ActivatedRoute객체의 트리를 만들어낸다.  Router서비스와 routerState속성을 사용하는 곳 어느곳에서나 RouterState에 접근이 가능하다.


요약

앱은 설정된 라우터를 하나 갖게된다. 라우터가 생성하는 뷰는 RouterOutlet에 표시되게 되고 RouterLink로 특정 라우트로 이동할 수 있다.


Router Part 

 Meaning

 Router

유효한 URL의 콤포넌트를 표시하고 한 콤포넌트에서 다른 콤포넌트로의 네비게이션을 관리한다. 

 RouterModule

앵귤러에서 분리된 모듈로 필요한 서비스프로바이더와 디렉티브들을 제공한다. 

 Routes

Route들의 배열로 URL경로와 콤포넌트간의 맵핑테이블이다. 

 Route

라우터가 URL패턴에 따라 콤포넌트를 어떻게 다룰지에 대해 정의한다. 대부분의 라우트는 경로와 콤포넌트로 구성된다. 

 RouterOutlet

라우터가 뷰를 표시할 directive(<router-outlet>)이다. 

 RouterLink

디렉티브로 클릭가능한 라우트 엘리먼트(routerLink)이다.  

 RouterLinkActive

css class로 routerLink가 active/inactive될때 적용된다. 

 ActivatedRoute

서비스로 각 라우트콤포넌트에 라우트파라메터, 스테틱데이터, resolve data, global query params그리고 global fragment정보를 제공한다.

 RouterState

route tree로부터 router의 상태정보를 제공한다. 

 Link parameter 배열

라우팅 명령으로 처리되는 배열로 RouterLink에 바인드하거나 Router.navigate메서드로 배열을 전달할 수 있다. 

 Routing component

RouterOutlet과 함께 앵귤러 콤포넌트로 라우터네비게이션에 기반하여 뷰를 표시한다. 



위에서 설명한것으로 라우팅을 적용한 앱을 만들어 볼수 있다.

자세한 설명이 필요하다면 링크 참조(https://angular.io/docs/ts/latest/guide/router.html)



신고
Posted by 삼스

티스토리 툴바