My Profile Photo

DongChanS's blog


수학과 학생의 개발일지


Angular (9) Tutorial - Routing(2) - dynamic routing & go-back

1) Navigating to hero details

Hero-Detail 컴포넌트를 이용하여 dynamic-routing을 해봅시다.

일단 detail에 해당하는 URL로 이동하면 router-outlet 태그에는 Hero-detail 컴포넌트를 보여주는게 목적입니다.

그런데 문제점이 하나 있습니다.

바로 Hero-detail 컴포넌트가 Heroes 컴포넌트에 종속되어 있다는 겁니다.

기존에는,

  1. Heroes 컴포넌트 안에 selectedHero 라는 속성이 있음.
  2. 각 영웅의 리스트를 클릭할 때 마다 event-handling을 통해서 selectedHero 의 값을 변화시킴
  3. selectedHero의 값을 Hero-detail 컴포넌트의 hero 속성에 바인딩하여 그 selectedHero의 정보를 출력함.

의 논리로 작동했는데, 오늘은 3번부분만 약간 바꿔서

  1. selectedHero의 값을 받아서 이 값을 기준으로 특정 히어로에 대한 라우트로 이동한다.

로 바꾸면 됩니다.

1-1. 동적으로 라우트를 만들어서 연결하기

  1. Detail 라우트를 만든다.

    // app-routing.module.ts
    const routes: Routes = [
      { path : 'heroes', component : HeroesComponent },
      { path: 'dashboard', component: DashboardComponent },
      { path: '', redirectTo: '/dashboard', pathMatch: 'full' },
      { path: 'detail/:id', component : HeroDetailComponent },
    ];
    

    :id 부분은 id라는 값에 따라서 동적으로 라우팅을 하겠다는 의미입니다.

  2. heroes 컴포넌트에다가 selectedHero값에 대한 링크를 추가한다.

       
    <a routerLink="/detail/{{hero.id}}/">
        <div>이름 : {{hero.name}}</div>
        <div>번호 : {{hero.id}}</div>
    </a>
       
    

    주의! : /detail/detail/는 엄청난 차이가 있습니다.

아마 이제 이동은 될겁니다.. 다만, 데이터가 정상적으로 출력이 안됩니다.

왜냐하면 이 :id값이 어떻게 Detail 컴포넌트에서 활용되는지를 명시하지 않았기 때문입니다.

1-2. id값을 컴포넌트에 적용하기

이제 /detail/11 이런식의 url이 들어오면, 11이라는 아이디를 가진 hero의 정보를 표현해줘야 합니다.

방식은 다음과 같습니다.

  1. /detail/11 과 같은 사용자가 입력한 주소를 얻는다.

    // hero-detail/hero-detail.component.ts
    import { ActivatedRoute } from '@angular/router';
    

    ActivatedRoute : 현재 활성화된 라우트에 대한 정보를 가지고 있는 클래스

  2. 그 주소에서 11부분만 가져온다.

    // 먼저 라우트의 객체를 생성함. 
    constructor(
        private route: ActivatedRoute,
        private heroService: HeroService,
      ) { }
    
    // id부분만 가져오기
    const id = +this.route.snapshot.paramMap.get('id');
    
    • route.snapshot : 컴포넌트가 생성된 이후에 생기는 라우터의 정보를 담은 static file(image)
    • paraMap : 라우트의 파라미터 밸류와 값을 맵핑하는 딕셔너리(파이썬의 그 딕셔너리라고 생각하면 될듯합니다.)
    • 그런데 값이 항상 string 타입이기 때문에 +를 넣어줘서 형변환.
  3. HeroService를 통해서 11 아이디를 가진 영웅을 찾아서 받아온다.

    • HeroService에 해당하는 아이디의 영웅을 가져오는 함수 만들기.

      // hero.service.ts
      getHero(id: number): Observable<Hero> {
          this.messageService.add(`${id}를 가진 영웅 FETCH 성공적`);
          const selectedHero = HEROES.find((hero) => (hero.id === id));
          return of(selectedHero);
        }
      
    • Detail 컴포넌트에서 HeroService의 함수를 이용하기.

      // hero-detail/hero-detail.component.ts
      ngOnInit() {
          this.getHero();
      }
      getHero(): void {
          const id = +this.route.snapshot.paramMap.get('id');
          this.heroService.getHero(id)
              .subscribe((hero) => {
              this.hero = hero;
          });
      }
      

이제 성공적으로 데이터가 출력됩니다.

6

1-3. Find the way back

브라우저의 뒤로가기처럼 이전 url상태를 기억하고 그 상태로 이동할 수 있는 뒤로가기버튼을 만들고 싶습니다.

  1. 뒤로가기 버튼 만들기

    <button (click)="goBack()">뒤로가기</button>
    
  2. goBack()만들기

    일단 Location이라는 클래스를 먼저 임포트해야합니다.

    Location은 브라우저와 상호작용을 할 수 있는 Angular에서 제공하는 특별한 Service입니다.

    // hero-detail/hero-detail.component.ts
    import { Location } from '@angular/common';
       
    constructor(
        private location: Location,
    ) { }
    

    그리고, 버튼을 클릭시, goBack()이라는 함수가 실행되며 이전의 url로 이동하고 싶습니다.

    goBack(): void {
        this.location.back();
    }
    

    location.back() 함수를 통해서 브라우저의 history stack의 한 단계 이전으로 이동하는 것입니다.

7

두개의 뒤로가기 버튼은 정말 완벽하게 동일합니다.

뜬금없이 /detail/12에서 /detail/11로 이동한 다음에 뒤로가기버튼을 클릭해도

/detail/12 로 이동해줍니다.

comments powered by Disqus