본문 바로가기

프론트엔드/앵귤러

공용 컴포넌트 - 리액티브 폼 인풋

반응형

컴포넌트의 재 상용성은 앵귤러나 리액트 등 프레임워크가 제공하는 장점 중 하나로 같은 코드를 중복작성할 필요성을 줄여줍니다. 오늘은 앵귤러에서 공용 인풋 컴포넌트를 만들어 보겠습니다.

구현하기

모듈추가

리액티브 폼즈 모듈을 모듈클래스에 추가합니다

컴포넌트 생성

공용으로 상용할 컴포넌트를 생성합니다

 ng g c components/shared/input

 

생성한 컴포넌트 클래스 파일에 폼 컨트롤과 돔요소를 연결하는 인터페이스를 구현합니다

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

구현된 메서드는 사용하지 않음으로 아래와 같이 정리 후 필요한 코드를 추가합니다.

 

인풋의 타입과 레이블은 인풋마다 다르므로 @Input을 통해 필드로 설정하여 변경 가능하도록 하고

 

컨스트럭터 추가 후 'NgControl'을 인젝션 합니다. 이때, 인젝션 되는 값에 부모가 존재하는 경우 기본적으로 부모의 값을 사용하는 것을 방지하고 고유의 값을 사용하기 위해 @Self()를 추가합니다.

 

마지막으로 타입오류를 방지하기 위해 'FormControl' 타입을 반환하는 겟터를 추가합니다

@Input() type: string = 'text';
@Input() label: string = '';

constructor(@Self() public controlDir: NgControl) {
  this.controlDir.valueAccessor = this;
}

writeValue(obj: any): void {}
registerOnChange(fn: any): void {}
registerOnTouched(fn: any): void {}
setDisabledState?(isDisabled: boolean): void {}

get control(): FormControl {
  return this.controlDir.control as FormControl;
}

템플릿으로 이동하여 아래와 같이 코드를 작성합니다(보기에서 스타일은 부트스트랩 클래스를 사용)

<div class="form-floating mb-3">
  <input [type]="type" [formControl]="control" [placeholder]="label" class="form-control"
  [ngClass]="(control.touched) ? control.invalid ? 'is-invalid' : 'is-valid' : null">
  <label>{{label}}</label>
  <div *ngIf="control.touched && control.errors?.['required']" class="text-danger">{{label}} Required</div>
  <div *ngIf="control.errors?.['email']" class="text-danger">Please Enter a Valid Email</div>
</div>

사용하기

사용하고자 하는 컴포넌트에서 폼에 필요한 제약조건 등을 설정하고

form = new FormGroup({
  email: new FormControl('', [Validators.required, Validators.email]),
  password: new FormControl('', [Validators.required]),
})

해당 템플릿에서 설정된 공용컴포넌트는 아래 코드를 통해 사용합니다

<app-input formControlName="email" [label]="'email'"></app-input>

이상으로 리액티브 폼 인풋 공용컴포넌트를 만드는 방법을 보았습니다

 

 

728x90
반응형