Anglar로 양식 구성 요소 만들기

25074 단어 tech
Anglar로 양식 UI를 만드는 구성 요소의 Tips입니다.
Anglar에서 양식 관리를 위한 ReactiveModule 준비
Vue.js 같은 형식의 UI 구성 요소와 생각이 다른 부분이 있으므로 주의해야 합니다.
https://angular.jp/guide/reactive-forms

창 UI 구성 요소 디자인


Reactive Form으로 양식을 만들 때
창 UI의 구성 요소는 다음과 같이 설계할 수 있습니다.
  • 모듈로 FormGroup/FormControl
  • 만들기
  • 서브어셈블리에서 FormControl 수신
  • 서브어셈블리가 내부 값 변화를 감지하고 FormCntrol 값을 변경
  • 부모를 통해 FormControl을 아이에게 맡기다
    아이의 UI 구성 요소는 Emit 이벤트 없이 UI 구성 요소를 구현할 수 있습니다.
    (Emit input/change는 가능하지만 부모가 아이의 활동을 처리하면 기술이 상당히 복잡해진다.)

    간단한 텍스트 창


    간단한 텍스트 창에서 UI 구성 요소를 구현할 때 코드는 다음과 같습니다.
    창 요소의 input/change를 가져와 값 변경과dirty/touched 표시 작업을 진행합니다.
    import { Component, Input, OnInit } from '@angular/core';
    import { FormControl } from '@angular/forms';
    
    @Component({
      selector: 'app-birth-input',
      templateUrl: './birth-input.component.html',
      styleUrls: ['./birth-input.component.css'],
    })
    export class BirthInputComponent implements OnInit {
      @Input() formControl: FormControl;
    
      onInput(e) {
        this.formControl.setValue(e.target.value);
        this.formControl.markAsDirty();
      }
      onChange() {
        this.formControl.markAsTouched();
      }
    }
    
    <div>
      <label>誕生日</label>
      <input 
        type="text"
        [value]="formControl.value" 
        (input)="onInput($event)" 
        (change)="onChange()" />
    </div>
    
    모 부품은 다음과 같은 형식을 사용할 수 있다.birth_on는 FormControl의 변수입니다.
    <app-my-uiform [formControl]="birth_on"></app-my-uiform>
    

    생년월일 UI 만들기


    상술한 것처럼 단지 하나의 표만 있는 경우는 매우 드물다
    일반 구성 요소로 분할된 창 UI를 만들 때
    나는 많은 형식적인 요소가 있다고 생각한다.
    여러 폼을 제어할 때 구성 요소 내부에서도 ReactiveForm을 이용하려고 하겠죠.
    이 경우 (input)를 통해 얻은 값의 변경이 아닙니다
    subscribe를 통해formControl의valueChanges의 변경 검사를 받습니다.
    import { Component, Input, OnInit } from '@angular/core';
    import { FormControl, FormGroup } from '@angular/forms';
    import { distinct } from 'rxjs/operators';
    
    interface DateObj {
      year: string;
      month: string;
      day: string;
    }
    
    @Component({
      selector: 'app-birth-input',
      templateUrl: './birth-input.component.html',
      styleUrls: ['./birth-input.component.css'],
    })
    export class BirthInputComponent implements OnInit {
      @Input() control: FormControl;
    
      dateform = new FormGroup({
        year: new FormControl(''),
        month: new FormControl(''),
        day: new FormControl(''),
      });
    
      ngOnInit() {
        this.setParentValue(this.control.value);
        this.control.valueChanges.pipe(distinct()).subscribe((r) => {
          this.setParentValue(r);
        });
    
        this.dateform.valueChanges.pipe(distinct()).subscribe((r: DateObj) => {
          if (!this.isValidDate(r)) {
            return;
          }
          this.control.setValue(this.dateStr(r));
        });
      }
    
      setParentValue(datestr: string) {
        const [year, month, day] = datestr.split('/');
        const dateObj: DateObj = { year, month, day };
        if (this.isValidDate(dateObj)) {
          this.dateform.setValue(dateObj);
        }
      }
    
      dateStr(date: DateObj) {
        return `${date.year}/${date.month}/${date.day}`;
      }
    
      isValidDate(date: DateObj) {
        const dateStr = this.dateStr(date);
        return !!Date.parse(dateStr); // null on Error
      }
    
      onInput() {
        this.control.markAsDirty();
      }
      onChange() {
        this.control.markAsTouched();
      }
    }
    
    <div>
      <label>誕生日</label>
      <form [formGroup]="dateform">
        <input
          type="text"
          formControlName="year"
          (input)="onInput()"
          (change)="onChange()"
        /><input
          type="text"
          formControlName="month"
          (input)="onInput()"
          (change)="onChange()"
        /><input
          type="text"
          formControlName="day"
          (input)="onInput()"
          (change)="onChange()"
        /></form>
    </div>
    

    Sample


    Select 목록에서 만든 창의 예는 다음과 같습니다.
    https://stackblitz.com/edit/angular-ivy-q8o4sb?file=src/app/birth-input/birth-input.component.ts

    좋은 웹페이지 즐겨찾기