angular CVA controlValueAccessor onpush

agnusdei·2023년 9월 14일
0

Angular의 ControlValueAccessor는 사용자 정의 입력 요소(커스텀 폼 컨트롤)를 생성하고 이를 Angular 폼 API와 통합하는 방법을 제공합니다. 이것은 사용자 정의 입력 요소를 Angular 폼 컨트롤처럼 다룰 수 있게 해주며, 폼의 유효성 검사, 상태 관리 및 값을 업데이트하는 등의 기능을 쉽게 구현할 수 있도록 합니다. OnPush 변경 감지 전략을 사용할 때 ControlValueAccessor를 효과적으로 사용하는 방법에 대해 설명하겠습니다.

OnPush 변경 감지 전략은 Angular에서 성능을 향상시키기 위한 전략 중 하나로, 컴포넌트의 입력 데이터가 변경될 때만 변경 감지를 수행하는 전략입니다. 이를 활용하여 사용자 정의 입력 요소를 최적화하려면 ControlValueAccessor와 함께 사용할 때 몇 가지 주의해야 할 사항이 있습니다.

아래는 ControlValueAccessor와 OnPush 변경 감지 전략을 사용하는 방법에 대한 상세 설명과 코드 예제입니다.

  1. ControlValueAccessor 구현

먼저, 사용자 정의 입력 요소를 생성하려면 ControlValueAccessor를 구현해야 합니다. 이 인터페이스를 구현하면 Angular가 사용자 정의 입력 요소를 폼 컨트롤로 인식할 수 있습니다. ControlValueAccessor 인터페이스는 다음 네 가지 메서드를 요구합니다.

  • writeValue(value: any): void: 모델로부터 값을 받아와서 입력 요소에 표시합니다.
  • registerOnChange(fn: any): void: 값이 변경될 때 호출될 콜백 함수를 등록합니다.
  • registerOnTouched(fn: any): void: 입력 요소가 터치되었을 때 호출될 콜백 함수를 등록합니다.
  • setDisabledState(isDisabled: boolean): void: 입력 요소를 비활성화 또는 활성화 상태로 설정합니다.

다음은 간단한 사용자 정의 입력 요소의 예제입니다.

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)" (blur)="onTouched()">
  `,
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => CustomInputComponent),
      multi: true,
    },
  ],
})
export class CustomInputComponent implements ControlValueAccessor {
  value: string = '';

  onChange: (value: any) => void = () => {};
  onTouched: () => void = () => {};

  writeValue(value: string): void {
    this.value = value;
  }

  registerOnChange(fn: (value: any) => void): void {
    this.onChange = fn;
  }

  registerOnTouched(fn: () => void): void {
    this.onTouched = fn;
  }

  setDisabledState(isDisabled: boolean): void {
    // Implement this if your input supports disabling
  }
}
  1. OnPush 전략 설정

사용자 정의 입력 요소의 부모 컴포넌트에서 OnPush 전략을 설정해야 합니다. 이렇게 하면 부모 컴포넌트의 변경 감지가 최적화됩니다. 부모 컴포넌트의 변경 감지 전략을 설정하려면 다음과 같이 컴포넌트의 데코레이터를 설정합니다.

@Component({
  selector: 'app-parent',
  templateUrl: './parent.component.html',
  changeDetection: ChangeDetectionStrategy.OnPush, // OnPush 전략 설정
})
export class ParentComponent {
  // ...
}
  1. 사용자 정의 입력 요소 사용

이제 사용자 정의 입력 요소를 부모 컴포넌트에서 사용할 수 있습니다. 이 예제에서는 Reactive Forms를 사용하여 폼 컨트롤과 바인딩합니다.

import { Component } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';

@Component({
  selector: 'app-parent',
  templateUrl: './parent.component.html',
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ParentComponent {
  form: FormGroup;

  constructor(private fb: FormBuilder) {
    this.form = this.fb.group({
      customInput: ['initialValue'], // FormControl 이름을 customInput으로 지정
    });
  }
}
<form [formGroup]="form">
  <!-- 사용자 정의 입력 요소를 폼 컨트롤에 바인딩 -->
  <app-custom-input formControlName="customInput"></app-custom-input>
</form>

이제 ControlValueAccessor를 사용하여 사용자 정의 입력 요소를 생성하고 OnPush 전략을 사용하여 성능을 최적화할 수 있습니다. 이를 통해 Angular 폼 API와 함께 사용자 정의 입력 요소를 효과적으로 통합할 수 있습니다.

ControlValueAccessor (CVA)는 Angular Forms에서 사용자 정의 입력 요소와 폼 컨트롤 간의 상호 작용을 관리하는 데 사용되는 인터페이스입니다. 이 인터페이스를 구현하면 Angular 폼 관련 작업을 지원하는 사용자 정의 입력 요소를 만들 수 있습니다. 이전의 설명과 연관하여 CVA를 사용할 때 OnPush 변경 감지 전략 및 markForCheck와 어떻게 관련되는지 자세히 설명하겠습니다.

  1. ControlValueAccessor의 구현:

    • ControlValueAccessor를 구현하면 사용자 정의 입력 요소를 폼 컨트롤과 쉽게 통합할 수 있습니다.
    • 사용자 정의 입력 요소에서 값 변경 및 터치 상태를 Angular Forms에 알리기 위해 ControlValueAccessor의 메서드를 구현합니다.
  2. OnPush 변경 감지 전략:

    • Angular에서 기본 변경 감지 전략은 상태 변경 시마다 뷰를 업데이트합니다. OnPush 전략은 컴포넌트의 입력 프로퍼티나 @Input 값이 변경될 때만 변경 감지를 수행하므로 성능을 최적화할 수 있습니다.
    • ControlValueAccessor를 구현한 컴포넌트에서 OnPush 전략을 사용하면 뷰를 업데이트할 때 더 효율적으로 변경 감지를 처리할 수 있습니다.
  3. markForCheck와의 연관:

    • ControlValueAccessor를 구현한 컴포넌트에서 OnPush 전략을 사용하면 해당 컴포넌트의 변경 감지가 자동으로 이루어지지 않습니다. 이 경우 markForCheck를 사용하여 수동으로 변경 감지를 트리거할 수 있습니다.
    • markForCheck를 호출하면 현재 컴포넌트와 그 부모 컴포넌트의 변경 감지를 트리거합니다. 이렇게 함으로써 사용자 정의 입력 요소에서 폼 컨트롤에 대한 변경 사항을 알리고, 폼 컨트롤의 값이 변경될 때 폼 컨트롤과 사용자 정의 입력 요소 간의 양방향 데이터 바인딩이 잘 동작합니다.

간단한 예를 통해 이를 이해해봅시다:

import { Component } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';

@Component({
  selector: 'app-custom-input',
  template: `
    <input type="text" [(ngModel)]="value">
  `,
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: CustomInputComponent,
      multi: true,
    },
  ],
  changeDetection: ChangeDetectionStrategy.OnPush, // OnPush 전략 사용
})
export class CustomInputComponent implements ControlValueAccessor {
  value: string = '';

  // ControlValueAccessor의 메서드 구현...

  // 값 변경 시 수동으로 변경 감지 트리거
  updateValue(newValue: string) {
    this.value = newValue;
    this.onChange(newValue); // ControlValueAccessor에서 정의한 메서드 호출
  }
}

위의 CustomInputComponent에서는 OnPush 전략을 사용하고, 값이 변경될 때 updateValue 메서드를 호출하여 값을 업데이트하고 onChange 메서드를 호출하여 변경 감지를 트리거합니다. 이렇게 하면 사용자 정의 입력 요소에서 폼 컨트롤에 대한 변경 사항을 알릴 수 있습니다.

결론적으로, ControlValueAccessor를 사용하여 사용자 정의 입력 요소와 폼 컨트롤을 통합할 때 OnPush 전략과 markForCheck를 함께 사용하면 성능을 최적화하고 양방향 데이터 바인딩을 원활하게 관리할 수 있습니다.

0개의 댓글