정글에서 온 개발자

Angular 동적 폼 만들기 본문

TIL

Angular 동적 폼 만들기

dev-diver 2024. 6. 26. 17:51

앵귤러 동적 폼


앵귤러에서 위와 같은 동적 폼을 만들기로 한다.
nz-zorro(Ant for Angular)도 같이 사용하였다.

HTML

<app-modal-add-button 
    title="연차신청"
    [okHandler]="handleOk"
>
    <div id="vacation-pickers">
        <div *ngFor="let vacation of vacations.controls; let i = index" [formGroup]="vacation">
            <nz-range-picker
                nzFormat="yyyy-MM-dd"
                formControlName="dateRange"
                (nzOnCalendarChange)="onCalendarChange($event, i)"
            ></nz-range-picker>
            @if(i!=0){
                <button nz-button nzType="default" (click)="removeVacation(i)">삭제</button>
            }
        </div>
    </div>
    <button nz-button nzType="primary" (click)="addVacation()">추가</button>
</app-modal-add-button>
  • 동적으로 생성되는 그룹 (vacation-pickers)를 만든다.
  • 그 안에 vacations.controls의 수만큼 반복한다.
    • i를 따로 선언해서 넘겨줘야 해서, @if 대신 *ngFor 디렉티브를 사용하였다.
  • form으로 제출할 값을 바꿔주는 이벤트 리스너를 달아준다. (onCalendarChange)
  • 동적으로 추가된 요소를 삭제할 버튼을 만든다. (가장 첫번째 요소는 삭제하지 못하게 하였다.)
  • 추가 버튼으로 요소를 동적으로 추가할 수 있게 한다.

.ts

export class ApplyVacationComponent {
  
  @Input() auth : Auth = {} as Auth
  vacations: FormArray<FormGroup>

  constructor(private fb: FormBuilder, private vacationService : VacationService) { 
    this.vacations = this.fb.array([
      this.fb.group({
        dateRange: [[]]
      })
    ])
  }

  addVacation() {
    this.vacations.push(this.fb.group({
      dateRange: [[]]
    }););
  }

  removeVacation(index: number) {
    this.vacations.removeAt(index);
  
  onCalendarChange(result: Array<Date | null>, index:number): void {
    this.vacations.at(index).get('dateRange')?.setValue(result);
  }

  handleOk = async (): Promise<void> => {
    const vacationPlans = this.vacations.value.map((vacation: any) => ({
      start_date: vacation.dateRange[0],
      end_date: vacation.dateRange[1],
    }));

    await this.vacationService.postVacationPlan(this.auth.member.id, {
      vacations: vacationPlans
    });
  }

}
  • vacations를 정의한다.
    • FormArray 뒤의 <FormGroup> 이 중요한데, html에서 [formGroup] 속성으로 넘겨주려면 타입을 formGroup으로 줘야 하기 때문이다.
  • addVacation에서 빌더를 통해 새 그룹을 만들어 넘겨준다.
  • removeVacation은 삭제하려는 인덱스를 찾아 삭제해준다.
  • onCalendarChange 이벤트 리스너가 수시로 dateRange를 찾아서 값을 할당해준다.
  • handleOK 로 제출시, 모든 vacations의 value에 대해서 range를 배열로 만들어 service에 넘겨준다.

해야할 것

  • 사실 이렇게만 넘길거면, FormGroup 사용할 것 없이 그냥 vacations array 를 만들고 그 안에 dateRange를 넣어도 무방하다.
  • 이렇게 formGroup을 사용한 이유는 form의 꽃, validation을 쉽게 사용하기 위해서다.
  • 그 내용은 다음 포스팅에서 다룰 예정이다.