Angular 애플리케이션에서 폼 컨트롤을 사용자 정의하고 제어하려면 ControlValueAccessor와 FormGroup를 이해하고 활용해야 합니다. 이 블로그 글에서는 이러한 개념을 상세하게 설명하고, 간단한 예제를 통해 실제로 어떻게 구현하는지 살펴보겠습니다.
ControlValueAccessor는 Angular에서 컴포넌트를 사용자 정의 폼 컨트롤로 래핑하고, Angular 폼 모델과 상호작용하기 위한 인터페이스입니다. 이를 구현한 컴포넌트는 모델 값을 설정하고 폼 컨트롤 값을 업데이트할 수 있습니다. 이를 위해 네 가지 주요 메서드를 구현해야 합니다.
registerOnChange(fn: any): 폼 컨트롤 값이 변경될 때 호출되는 콜백 함수를 등록합니다.registerOnTouched(fn: any): 폼 컨트롤이 터치(사용자 상호작용)될 때 호출되는 콜백 함수를 등록합니다.writeValue(obj: any): 모델로부터 폼 컨트롤로 값을 쓰는 메서드로, 초기값을 설정하거나 외부에서 값을 주입하는 데 사용됩니다.setDisabledState(isDisabled: boolean): 폼 컨트롤을 활성화 또는 비활성화하는 메서드로, 컨트롤의 상태를 관리합니다.간단한 사용자 정의 입력 요소를 생성하고 ControlValueAccessor를 구현하여 폼 컨트롤과 상호작용하는 방법을 살펴보겠습니다.
import { Component, forwardRef } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
@Component({
selector: 'app-custom-input',
template: `
<input type="text" [(ngModel)]="value" (input)="onChange($event.target.value)" [disabled]="disabled">
`,
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => CustomInputComponent),
multi: true
}
]
})
export class CustomInputComponent implements ControlValueAccessor {
value: string = '';
disabled: boolean = false;
// ControlValueAccessor 구현
onChange: any = () => {};
onTouch: any = () => {};
writeValue(value: any): void {
this.value = value;
}
registerOnChange(fn: any): void {
this.onChange = fn;
}
registerOnTouched(fn: any): void {
this.onTouch = fn;
}
setDisabledState(isDisabled: boolean): void {
this.disabled = isDisabled;
}
}
위에서 구현한 CustomInputComponent를 다른 컴포넌트에서 사용하는 예제를 살펴보겠습니다.
import { Component } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
@Component({
selector: 'app-root',
template: `
<form [formGroup]="formGroup">
<app-custom-input formControlName="customInput"></app-custom-input>
</form>
<button (click)="toggleDisabled()">Toggle Disabled</button>
`
})
export class AppComponent {
formGroup: FormGroup;
constructor(private formBuilder: FormBuilder) {
this.formGroup = this.formBuilder.group({
customInput: ['Initial Value']
});
}
toggleDisabled() {
const customInputControl = this.formGroup.get('customInput');
if (customInputControl) {
customInputControl.disabled ? customInputControl.enable() : customInputControl.disable();
}
}
}
ControlValueAccessor 구현: CustomInputComponent에서는 ControlValueAccessor를 구현하여 폼 컨트롤과의 상호작용을 처리합니다.
writeValue 메서드를 사용하여 초기값을 설정하거나 외부에서 값을 주입합니다.registerOnChange와 registerOnTouched 메서드를 사용하여 폼 컨트롤의 변경 이벤트와 터치 이벤트를 처리하고 콜백 함수를 등록합니다.setDisabledState 메서드를 사용하여 폼 컨트롤을 활성화 또는 비활성화합니다.템플릿과 폼 연동: 컴포넌트 템플릿에서는 ngModel 또는 formControlName을 사용하여 CustomInputComponent와 폼 컨트롤 간의 연결을 설정합니다.
사용 예제: CustomInputComponent를 다른 컴포넌트에서 사용하여 폼을 구성하고 사용자 정의 입력 요소를 활용합니다.
이제 ControlValueAccessor와 FormGroup를 활용하여 사용자 정의 폼 컨트롤을 만드는 방법을 상세하게 이해하셨을 것입니다. 이러한 기술을 사용하면 Angular에서 폼 컨트롤을 더욱 유연하게 다룰 수 있으며, 재사용 가능한 사용자 정의 입력 요소를 생성할 수 있습니다.