8. 양방향 바인딩
양방향 바인딩을 활용하면 컴포넌트끼리 데이터를 공유할 수 있다. 양방향 바인딩은 자식 컴포넌트에서 발생하는 이벤트를 감지하는 바인딩과 자식 컴포넌트에 데이터를 전달하는 프로퍼티 바인딩이 결합된 형태이다.
1. 사전지식
양방향 바인딩에 대해 제대로 이해하려면 이런 내용에 대해 이해하고 있는 것이 좋다:
양방향 바인딩은 프로퍼티 바인딩과 이벤트 바인딩이 결합된 것이다:
2. 양방향 바인딩 추가하기
Angular는 대괄호와 소괄호를 함께 사용하는 [()]
라는 문법을 양방향 바인딩 문법으로 제공한다. 이 문법은 프로퍼티 바인딩 문법([]
)과 이벤트 바인딩 문법(()
)이 결합된 형태이다.
3. 양방향 바인딩이 동작하는 과정
양방향 데이터 바인딩이 동작하려면 자식 컴포넌트에 @Input()
데코레이터가 지정된 프로퍼티가 있어야 하며, 이 프로퍼티 이름이 input
이라면 inputChange
프로퍼티에 @Output()
데코레이터가 지정되어야 한다. 예를 들면 size
프로퍼티에 @Input()
데코레이터가 지정되어 있어야 하며, sizeChange
프로퍼티에 @Output()
데코레이터가 지정되어 있어야 한다.
아래 예제에서 sizerComponent
에는 size
프로퍼티와 sizeChange
프로퍼티가 존재한다. 이 프로퍼티 중 size
프로퍼티에는 @Input()
데코레이터가 지정되어 있기 때문에 데이터가 sizerComponent
안으로 전달될 수 있다. 그리고 sizeChange
프로퍼티에는 @Output()
데코레이터가 지정되어 있기 때문에 sizerComponent
에서 부모 컴포넌트 방향으로 데이터가 전달될 수 있다.
sizerComponent
에는 메서드가 3개 더 있다. dec()
메서드는 폰트 크기를 줄이는 메서드이고, inc()
메서드는 폰트 크기를 키우는 메서드이다. 두 메서드는 resize()
메서드를 활용해서 최소값/최대값 범위 안에서 size
프로퍼티 값을 조정하며, 새로 변경된 값으로 이벤트를 생성해서 보낸다.
export class SizerComponent {
@Input() size!: number | string;
@Output() sizeChange = new EventEmitter<number>();
dec() {
this.resize(-1);
}
inc() {
this.resize(+1);
}
resize(delta: number) {
this.size = Math.min(40, Math.max(8, +this.size + delta));
this.sizeChange.emit(this.size);
}
}
sizerComponent
템플릿에는 버튼이 2개 있으며 이 버튼은 각각 inc()
메서드와 dec()
메서드에 클릭 이벤트로 연결되어 있다. 이후에 사용자가 버튼을 클릭하면 연결된 메서드가 실행되면서 resize()
메서드를 호출하고, 새로 변경된 값으로 sizeChange
이벤트가 발생한다.
<div>
<button (click)="dec()" title="smaller">-</button>
<button (click)="inc()" title="bigger">+</button>
<label [style.font-size.px]="size">FontSize: {{size}}px</label>
</div>
AppComponent
템플릿에는 fontSizePx
프로퍼티가 SizerComponent
와 양방향으로 바인딩되어 있다.
<app-sizer [(size)]="fontSizePx"></app-sizer>
<div [style.font-size.px]="fontSizePx">Resizable Text</div>
AppComponent
에 있는 fontSizePx
프로퍼티는 SizerComponent.size
값에 따라 초기화되며, 예제에서는 16
이다.
이제 버튼을 클릭하면 AppComponent.fontSizePx
프로퍼티 값이 갱신된다. 그러면 변경된 프로퍼티 값에 따라 스타일이 바인딩되기 때문에 화면에 표시된 글자도 커지거나 작아진다.
양방향 바인딩 문법은 프로퍼티 바인딩 문법과 이벤트 바인딩 문법을 짧게 줄여놓은 것이다. 두 바인딩 문법은 아래 코드처럼 풀어서 작성할 수도 있다.
<app-sizer [size]="fontSizePx" (sizeChange)="fontSizePx=$event"></app-sizer>
$event
변수에는 SizerComponent.sizeChange
이벤트로 보낸 데이터가 담겨 있다. 이 변수의 값은 AppComponent.fontSizePx
에 할당된다.
Note
- 표준 HTML 엘리먼트는 값을
x
에 저장하고xChange
로 이벤트를 보내는 패턴을 사용하지 않기 때문에 폼에 양방향 바인딩을 사용하려면ngModel
을 활용해야 한다. - 폼에서 양방향 바인딩을 사용하는 방법에 대해 자세하게 알아보려면 NgModel 문서를 참고한다.