내용으로 건너뛰기
Angular에서 @Input()를 사용한 구성 요소 간 통신

Angular에서 @Input()를 사용한 구성 요소 간 통신

이 기사에서는 자식 구성 요소가 @Input() 속성을 사용하여 부모 구성 요소와 상호 작용하는 방법에 중점을 둘 것입니다. 또한 입력 메시지를 가로채고 입력 메시지의 변경 사항을 기록하는 방법도 살펴보겠습니다.

8min read

Angular에서 구성 요소는 데이터 또는 이벤트를 전달하여 다른 구성 요소와 데이터 및 정보를 공유할 수 있습니다. 구성 요소는 다른 구성 요소 내에서 사용할 수 있으므로 구성 요소 계층 구조를 만들 수 있습니다. 다른 구성 요소 내에서 사용되는 구성 요소를 하위 구성 요소라고 하고 둘러싸는 구성 요소를 부모 구성 요소로 합니다.

Parent Child component relation

아래 목록에서 생성된 구성 요소를 고려해 보겠습니다. 다른 컴포넌트 내에서 사용할 AppChildComponent라는 컴포넌트를 만들었습니다.

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

@Component({
  selector : 'appchild',
  template : `<h2> Hi{{greetMessage}} < / h2 >`
}) export class AppChildComponent {
  greetMessage : string = "I am Child";
}

AppComponent라는 또 다른 구성 요소도 만들었습니다. AppComponent 내부에서는 AppChildComponent 를 사용하고 있습니다.

import{Component} from '@angular/core';
import{AppChildComponent} from './appchild.component';

@Component({
  selector : 'my-app',
  template : `<h1> Hello{{message}} < / h1 > <br /><appchild></ appchild>
  `,
}) export class AppComponent {
  message : string = "I am Parent";
}

위의 목록에서 AppComonent는 AppChildComponent를 사용하고 있으므로 AppComponent는 부모 구성 요소이고 AppChildComponent는 자식 구성 요소입니다.

상위 구성 요소에서 하위 구성 요소로 데이터 전달

부모 구성 요소에서 자식 구성 요소로 데이터를 전달하는 것부터 시작하겠습니다. 이는 input 속성을 사용하여 수행할 수 있습니다. @Input 데코레이터 또는 입력 속성은 부모 구성 요소에서 자식 구성 요소로 데이터를 전달하는 데 사용됩니다. 이렇게 하려면 아래 목록과 같이 자식 AppChildComponent를 수정해야 합니다.

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

@Component({
  selector : 'appchild',
  template : `<h2> Hi{{greetMessage}} < / h2 >`
}) 

export class AppChildComponent implements OnInit {
  @Input() greetMessage : string;
  constructor() {}
  ngOnInit() {}
}

아시다시피 @Input() 데코레이터를 사용하여 greetMessage 속성을 수정했습니다. 또한 나중에 데모에서 사용할 onInit를 구현했습니다.  따라서 기본적으로 자식 구성 요소에서 greetMessage 속성의 값을 부모 구성 요소에서 설정할 수 있도록 @Input() 데코레이터로 greetMessage 속성을 데코레이션했습니다.

다음으로 부모 구성 요소 AppComponent를 수정하여 자식 구성 요소에 데이터를 전달해 보겠습니다.

import{Component} from '@angular/core';
import{AppChildComponent} from './appchild.component';

@Component({
  selector : 'my-app',
  template : `<h1> Hello{{message}} < / h1 > <br />
      <appchild[greetMessage] = "childmessage"></ appchild>
  `,
}) 
export class AppComponent {
  message : string = "I am Parent";
  childmessage : string = "I am passed from Parent to child component"
}

부모 구성 요소에서 자식 구성 요소의 속성 greetMessage 값을 설정합니다. 자식 구성 요소에 값을 전달하려면 대괄호 안에 자식 구성 요소 속성을 전달하고 해당 값을 부모 구성 요소의 속성으로 설정해야 합니다. 부모 구성 요소에서 자식 구성 요소의 greetMessage 속성으로 childmessage 속성의 값을 전달합니다.

부모 구성 요소에서 GreetMessage 속성으로 ChildMessage 속성 값 전달

하위 구성 요소의 상위 구성 요소의 입력 가로채기

자식 구성 요소 내부의 부모 구성 요소에서 전달된 데이터를 가로채야 하는 요구 사항이 있을 수 있습니다. 이것은 입력 속성에서 gettersetter를 사용하여 수행할 수 있습니다.

자식 구성 요소에서 들어오는 메시지를 가로채고 이를 일부 문자열과 결합하고 싶다고 가정해 보겠습니다.  이를 위해 _greetmessage라는 속성을 만들고 @Input() 데코레이터를 사용하여 _greetmessage 속성에 대한 getter와 setter를 만들었습니다. getter에서는 부모 구성 요소의 입력을 가로채 문자열과 결합합니다. 이 작업은 다음 목록에 표시된 대로 수행할 수 있습니다.

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

@Component({
  selector : 'appchild',
  template : `<h2> Hi{{_greetMessage}} < / h2 >`
}) 

export class AppChildComponent implements OnInit {
  _greetMessage : string;
  constructor() {}
  ngOnInit() {}

  @Input() set greetMessage(message : string) {
    this._greetMessage = message + " manipulated at child component";
  }
  get greetmessage() { return this._greetMessage; }
}

setter에서는 상위 구성 요소에서 들어오는 데이터를 조작하고 여기에 일부 텍스트를 추가합니다. 부모 구성 요소의 동작은 메시지를 가로채는지 여부에 관계없이 변경되지 않습니다. 더 자세히 알아보기 위해 다른 예를 들어 부모에서 전달된 이름을 표시하는 자식 구성 요소를 만들어 보겠습니다. 부모가 빈 이름 값을 전달하면 자식 구성 요소에 기본 이름이 표시됩니다. 이를 위해 하위 구성 요소에서 setter를 수정했습니다. setter에서 이름 값이 전달되었는지 여부를 확인하고 있습니다. 전달되지 않았거나 빈 문자열인 경우 name 값이 기본값에 할당됩니다. 아래 목록과 같이 하위 구성 요소를 만들 수 있습니다.

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

@Component({
  selector : 'appchild',
  template : `<h2>{{_name}} < / h2 >`
}) 

export class AppChildComponent implements OnInit {
  _name : string;
  constructor() {}
  ngOnInit() {}

  @Input() set Name(name : string) {
    this._name = (name && name.trim()) || "I am default name";
  }
  get Name() { return this._name; }
}

@Input() setter에서 알 수 있듯이 부모에서 전달된 값을 가로채고 빈 문자열인지 확인합니다. 빈 문자열인 경우 하위 구성 요소의 이름에 기본값을 할당합니다.

아래 목록과 같이 부모 구성 요소 AppComponent 내에서 AppChildComponent를 사용할 수 있습니다.

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

@Component({
  selector : 'my-app',
  template : `<h1> Hello{{message}} < / h1 > <br />

      <appchild *ngFor = "let n of childNameArray"[Name] = "n"></ appchild>
  `,
}) 
export class AppComponent {
  message : string = "I am Parent";
  childmessage
      : string = "I am passed from Parent to child component" childNameArray =
            [ 'foo', 'koo', ' ', 'moo', 'too', 'hoo',''];
}

부모 구성 요소 내에서 childNameArray 속성의 모든 항목을 통해 자식 구성 요소를 반복하고 있습니다. childNameArray의 몇 가지 항목은 빈 문자열이며, 이러한 빈 문자열은 자식 구성 요소 setter에 의해 가로채서 기본값으로 설정됩니다. 자식 구성 요소는 아래 이미지와 같이 부모 구성 요소에서 전달된 값을 렌더링합니다.

자식 컴포넌트는 부모 컴포넌트에서 전달된 값을 렌더링합니다.

ngOnChanges 및 @Input() 데코레이터

구성 요소의 OnChanges 수명 주기 후크를 사용하여 모든 입력 속성 변경 사항을 가로챌 수 있습니다. Input 속성이 부모 구성 요소에서 변경될 수 있고 자식 구성 요소에서 가로채야 하는 데는 여러 가지 이유가 있을 수 있습니다. 이 작업은 OnChanges 수명 주기 후크에서 수행할 수 있습니다.

counter라는 Input 변수의 변경 사항을 기록해야 한다고 가정해 보겠습니다. 카운터의 값은 부모 구성 요소에 의해 설정되며 부모 구성 요소에서 변경할 수 있습니다. 부모 구성 요소에서 카운터 값이 변경될 때마다 하위 구성 요소의 변경 사항을 기록해야 합니다. 아래 목록과 같이 하위 구성 요소를 만들었습니다.

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

@Component({
  selector : 'appchild',
  template : `<h2>{{counter}} < / h2 > <h2> Value Changed</ h2><ul>
      <li *ngFor = "let c of changeLog">{{c}} < / li >
      </ ul> 
    `
}) 

export class AppChildComponent implements OnChanges {
  @Input() counter = 0;
  changeLog : string[] = [];
  constructor() {}

  ngOnChanges(changes : {[propKey:string] : SimpleChange}) {
    let log : string[] = [];
    for (let p in changes) {
      let c = changes[p];
      console.log(c);
      let from = JSON.stringify(c.previousValue);
      let to = JSON.stringify(c.currentValue);
      log.push(`${p} changed from ${from} to $ { to }`);
    }

    this.changeLog.push(log.join(', '));
  }
}

기본적으로 우리는 다음을 수행하고 있습니다.

  1. OnChanges 수명 주기 후크 구현
  2. ngOnChanges 메서드에서 SimpleChange 유형의 배열을 전달합니다.
  3. 모든 변경 사항을 반복하고 문자열 배열로 푸시

카운터 값이 변경될 때마다 자식 구성 요소는 이전 값과 현재 값을 기록합니다. 각 입력 속성에 대한 이전 값과 현재 값의 읽기는 아래 이미지와 같이 ngOnChnages 메서드에서 수행됩니다.

각 입력 속성에 대한 이전 값과 현재 값의 읽기는 다음과 같이 ngOnChnages 메서드에서 수행됩니다

부모 구성 요소에서 단추 클릭 시 속성을 계산하기 위해 새 난수를 할당하고 count 속성을 자식 구성 요소의 입력 속성 카운터 값으로 설정합니다.

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

@Component({
  selector : 'my-app',
  template : `<h1> Hello{{message}} < / h1 >
      <br /><button(click) = "nextCount()"> change count</ button><br />
      <appchild[counter] = "count"></ appchild> 
  `,
}) 

export class AppComponent {
  count : number = 0;

  nextCount() {
    console.log("hahahah");
    this.count = this.getRandomIntInclusive(this.count, this.count + 1000);
  }

  getRandomIntInclusive(min : number, max : number) {
    min = Math.ceil(min);
    max = Math.floor(max);
    return Math.floor(Math.random() * (max - min + 1)) + min;
  }
}

기본적으로 부모 구성 요소에서 부모 구성 요소의 count 속성으로 자식 구성 요소의 입력 속성 카운터 값을 설정하고 버튼을 클릭할 때마다 값을 변경합니다.  부모 구성 요소에서 count 속성 값이 변경될 때마다 카운터 입력 속성의 값이 자식 구성 요소에서 변경되고 변경된 값이 기록됩니다.

응용 프로그램을 실행하면 아래 이미지와 같이 변경 로그와 함께 예상 출력을 얻을 수 있습니다.

응용 프로그램을 실행하면 변경 로그와 함께 예상 출력을 얻을 수 있습니다.

결론

이 기사에서는 부모 구성 요소에서 하위 구성 요소로 데이터를 전달하는 방법을 배웠습니다. 또한 입력 메시지를 가로채고 변경 사항을 기록하는 방법도 배웠습니다. 추가 게시물에서는 구성 요소 통신의 더 많은 측면을 살펴보겠습니다. 이 게시물이 도움이 되었기를 바라며, 읽어주셔서 감사합니다.

데모 요청