프로필사진
[Angular] 커스텀 컴포넌트에 데이터 양방향으로 바인딩하는 방법

2020. 7. 13. 18:29🔴 Angular

300x250

Angular의 기본 양방향 바인딩은 '[()]'으로 구현한다.
이를 ngModel이라는 디렉티브를 이용하여 아래와 같이 html과 ts를 양방향으로 묶을 수 있다.

*ngModel를 사용하기 위해선 FormsModule를 import해야한다 :

import { FormsModule } from '@angular/forms'; 

@NgModule({ 
	imports: [ FormsModule ]
    	})

그리고 html에서 input에 이런식으로 ngModel을 사용한다 :

<input type="text" [(ngModel)]="myText">

이렇게 하면 html의 input값과 ts의 myText가 바인딩되어 input값이 바뀌면 myText값도 바뀐다.
하지만 이는 엄밀히 따지면 양방향 바인딩이 아니라 내부적으로 프로퍼티 바인딩 & 이벤트 바인딩을 사용한 것이다.

즉, [(ngModel)] 은
[ngModel] = "myText" + (ngModelChange) = "myText = $event" 인 것이다.


이 원리를 활용하여 우리는 커스텀한 컴포넌트에서 원하는 변수를 양방향으로 바인딩할 수 있다.

1. @Input, @Output - 양방향으로 바인딩 하기

<app-my-control [(myProp)]="value"></app-my-control>

<app-my-control> 컴포넌트에서 'myProp'을 'value'에 바인딩을 하려면,
app-my-control.component에서 아래처럼 @Input()과 @Output()을 만들어야 한다.

@Input()
myProp: string;

@Output()
myPropChange = new EventEmitter<string>();

여기서 주의해야 할 점은!!
@Output()은 Input의 prop 이름 + 'Change' 형태가 되어야 한다는 것이다.

app-my-control 컴포넌트에서 이를 사용한 부모 컴포넌트에게 새로운 데이터로 업데이트 하려면
코드 내에서 'this.myPropChange.emit("newData!!")'로 event를 emit하면 된다.

2. getter, setter - 자동으로 데이터 업데이트하기

만약 데이터가 바뀔때마다 자동으로 emit하는 것을 원한다면

private _myProp: string;

@Input() get myProp() {
	return this._myProp
};

set myProp(val:string) {
	this._myProp = val;
    this.myPropChange.emit(this.myProp);
}

이런식으로 @Input을 getter & setter로 만들어 setter코드 안에 emit을 하도록 바꿔주면 된다.


사용 예제

<report-add-panel [(currentPanel)]="currentPanel"></report-add-panel>

report-add-panel.component의 currentPanel & 부모 컴포넌트의 currentPanel를 양방향 바인딩 하였다.

@Output() public currentPanelChange = new EventEmitter<string>();

private _currentPanel = '';

@Input() get currentPanel() {
    return this._currentPanel;
  }

  set currentPanel(val) {
    this._currentPanel = val;
    this.currentPanelChange.emit(this.currentPanel);
  }

currentPanel변수의 @Input & @Output을 만들고,
Output의 이름은 변수명+Change,
Input의 setter 내에서는 event를 emit해주는 코드를 넣었다.

그러면 이렇게 [(ngModel)] 처럼 Input과 Output이 연결된 것을 확인할 수 있다.

this.currentPanel = '';

이처럼 만약 부모 컴포넌트나 자식 컴포넌트 내에서 currentPanel의 값을 변경한다면,
데이터가 양방향으로 바인딩 되어있기 때문에 부모 & 자식 컴포넌트 모두 변경된 데이터 값으로 업데이트 된다.

300x250