주의! 이 글은 철저히 본인의 기억을 다시 떠올리기 위해서 만든 글입니다.
CVA a.k.a Control Value Accessor
앵귤러의 중요한 기능이지만 사용할 기회가 적어서 ( 대략 까먹을때쯤에 필요해짐... ) 나중을 위해서 블로깅 해둡니다.
Angular Forms API중 하나인데 컴포넌트와 DOM Element간 커넥션을 만들어 form을 조작하는 기능이다.
( 먼소리지... )
한 줄로 요약하면 컴포넌트를 Form의 기능처럼 사용하는 방법이다.
ctrl = new FormControl('');
이렇게 FormControl가 있는 컴포넌트에서
<app-custom-input [formControl]="ctrl"></app-custom-input>
CVA 컴포넌트에 FormControl 디렉티브를 사용해서 붙이면 사용이 가능하다.
일단 CVA 전체 코드 먼저 투척한다.
import { Component, forwardRef, OnInit } from '@angular/core';
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';
@Component({
selector: 'app-custom-input',
templateUrl: './custom-input.component.html',
styleUrls: ['./custom-input.component.css'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => CustomInputComponent),
multi: true,
},
],
})
export class CustomInputComponent implements ControlValueAccessor {
onChange: any = () => {}; // UI 변경시 실행해야하는 함수, 위 Form에 전파됨 CVA -> form
onTouch: any = () => {}; // UI Element touch시 실행해야하는 함수 Form에 전파됨 CVA -> form
val = '';
// Form에서 값이 변경될시 CVA 값을 바꾸는 함수 form -> CVA
writeValue(value: any): void {
this.val = value;
}
// 함수 등록용 함수
registerOnChange(fn: any): void {
console.log('registerOnChange run');
this.onChange = (value) => {
console.log('change Run');
fn(value);
};
}
// onTouched 함수 등록용 함수
registerOnTouched(fn: any): void {
console.log('registerOntouched run');
this.onTouch = (value) => {
console.log('touch Run');
fn(value);
};
}
inputRun(event: Event) {
const inputElement = event.target as HTMLInputElement;
this.val = inputElement.value;
this.onChange(this.val);
this.onTouch(this.val);
}
}
코드를 하나씩 까보자.
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => CustomInputComponent),
multi: true,
},
],
C.V.A 컴포넌트에는 항상 다음과 같은 providers가 붙어야한다. provide로 NG_VALUE_ACCESSOR 토큰을 내려보내줘야하고 useExisting으로 자신을 내보내야 C.V.A 가 된다고 한다.
CVA는 다음과 같은 메소드들이 있다.
writeValue, onChange, onTouch, registerOnChange, registerOnTouced
writeValue 함수는 form -> CVA로 데이터가 전파되는 함수이다.
form의 값이 변경되면 writeValue 함수도 호출되서 C.V.A 상태를 이곳에서 변경할 수 있다.
// Form에서 값이 변경될시 CVA 값을 바꾸는 함수 form -> CVA
writeValue(value: any): void {
this.val = value;
}
registerOnChange, registerOnTouced은 컴포넌트가 실행되면 함께 실행되는 함수다
각각 매개변수로 onChange, onTouch 함수를 보내는데 이를 C.V.A에서 저장하여 나중에 활용해야한다.
onChange, onTouch 함수는 CVA -> form으로 데이터를 전파하는 함수다.
inputRun(event: Event) {
const inputElement = event.target as HTMLInputElement;
this.val = inputElement.value;
this.onChange(this.val);
this.onTouch(this.val);
}
이경우 위의 ctrl값이 onChange 함수에 의해서 변경된다.
E.O.D