본문 바로가기
프로그래밍/Angular

앵귤러 기초(Angular basic) 18.컴포넌트 중첩(Nested Component)

by 신나요 2022. 1. 27.

컴포넌트는 중첩해서 사용이 가능합니다.

컴포넌트를 중첩해서 사용해보고 컴포넌트간의 통신이 어떻게 이뤄지는지 알아보겠습니다.


중첩 컴포넌트

중첩된 컴포넌트를 시각적으로 표현해 보았습니다.

중첩 컴포넌트

 

상위 컴포넌트에서 하위 컴포넌트를 두개(sub1, sub2) 사용하고 있습니다.

외부 컴포넌트를 컨테이너 또는 상위 구성 요소라고 하며 내부 컴포넌트를 중첩 또는 하위 구성 요소라고 합니다. 

다른 표현으론 부모 컴포넌트와, 자식 컴포넌트로 불리기도 합니다.

이제 실제 코드에서 중첩된 구조의 컴포넌트를 살펴보겠습니다.

 

컴포넌트 분리하기

아래 화면을 보면 테이블에서 영화의 평점을 숫자로 표시하고 있습니다.

 

여기 숫자로 표시되는 평점을 별 5개의 등급 표현으로 시각적으로 바꾸고 싶습니다.

별과 같은 시각적 표현을 사용하여 등급 번호를 표시하면 사용자가 숫자의 의미를 더 빠르고 쉽게 해석할 수 있습니다.

 

기존 MovieListComponent에 코드를 추가하여 별을 표시하는 대신 별도의 컴포넌트로 만드는게 좋을것 같습니다.

컴포넌트를 별도로 분리하면 해당 기능의 템플릿과 논리가 캡슐화된 상태로 유지되어 재사용할 수 있습니다.

 


컴포넌트 작성

평점을 별로 표현시킬 부품을 만들어 보겠습니다.

컴포넌트 파일을 만드는 것부터 시작하겠습니다.

컴포넌트 파일 작성

StarScoreComponent는 애플리케이션 내의 어느 곳에서도 사용할 수 있기 때문에 shared폴더에 모든 컴포넌트 구성 요소를 만들었습니다.

 

 먼저 템플릿을 살펴보겠습니다.

star-score.component.html

스타일 시트에서는 Font Awesome Star 아이콘을 사용하여 별 다섯 개를 표시합니다.

안쪽 div 요소는 별 5개를 표시하기 위한 크기를 75px로 설정하였습니다.

그런 다음 바깥 div 요소는 style.width.px cropWidth 프로퍼티 바인딩 하였습니다.

cropWidth 변화에 영화 점수에 따라 바깥 div요소의 width가 75~0사이로 변할 것 입니다.

이 기법은 4.5개의 별만 나타나도록 잘라지는 너비를 설정하여 5개의 별 중 4.5개의 별과 같은 부분적인 별의 표시가 가능하게 합니다.

 

스타일 시트의 내용은 아래와 같습니다.

star-score.component.scss

영역을 자르고 하위 요소는 감추기 위해 crop클래스에 overflow:hidden 주었습니다.

 

컴포넌트 내용은 아래와 같습니다.

star-score.component.ts

클래스에 정의된 프로퍼티를 살펴보겠습니다.

 

rating 부모 컴포넌트에서 가져와야 값 입니다. 지금은 4로 하드 코딩해 놓겠습니다.

cropWidth 템플릿에 정의된 별의 너비의 값을 관리합니다.

하나에 15px 가지게 것이며, 지금은 기본값으로 75 별5개의 너비를 설정해 두었습니다.

그런 다음 cropWidth의값은 rating을 기준으로 다시 계산됩니다.

어디서 계산을 다시 해야 할까요?

부모 컴포넌트에서 rating이 변경할 때마다 cropWidth이 다시 계산 되어야 합니다.

처리에 가장 적합한 곳은 OnChanges 라이프사이클 훅입니다.

 

클래스에 OnChanges 인터페이스를 구현하고 OnChanges 인터페이스의 ngOnChanges 메소드에 대한 코드를 작성합니다.

ngOnChanges  메소드에서 rating을 사용하여 cropWidth를 할당합니다.

별 5개의 총크기는 75 px이고, 별 하나는 75를 5로 나눈 것입니다.

cropWidth를 별 하나의 값과 rating 곱해줍니다

예를 들어 등급이 4인 경우 4 곱하기 75를 5로 나눈 값은 60픽셀입니다.

템플릿에서는 이렇게 계산된 cropWidth style.width.px  바인딩 해 효과적으로 4개의 별만 표시합니다. 

 

지금 단계에서 브라우저에서 살펴보겠습니다.

그전에 만든 컴포넌트를 부모 컴포넌트에 넣어줘야 되겠죠?

만든 컴포넌트를 모듈에 선언 하는 것도 잊지 말아주세요.

이제 확인해 보겠습니다.

평점의 숫자가 별로 바뀐 것은 좋으나, 아직까지 별이 5개로 고정되어 출력 되네요.

 

이유는 첫째로 부모 컴포넌트에서 rating 값을 받아오지 않았고,

둘째로 rating값을 기반으로 cropWidth 제대로 계산되지 않아서 입니다.

현재 코드는 OnChanges 라이프사이클 이벤트가 발생할 , ngOnChanges메서드에서 cropWidth속성을 변경하고 있습니다.

그러나 OnChanges input속성의 변경 사항을 감시하므로 컴포넌트에 input속성이 없는 지금 상태로는 OnChanges라이프사이클 이벤트는 발생하지 않습니다

따라서 cropWidth속성이 변경되지 않았고, 템플릿도 항상 별이 5개로 고정되어 출력되고 있습니다.


여기까지 수고하셨습니다.

다음 포스트에서 컴포넌트간의 통신하는 방법에 대해 알아보겠습니다.

그리고 @input 이용하여 StarScore컴포넌트의 문제점을 해결해 보도록 하겠습니다.

댓글