[angular] 반응 양식-필드를 터치 한 것으로 표시

모든 양식의 필드를 터치 한 것으로 표시하는 방법을 찾는 데 문제가 있습니다. 주요 문제는 필드를 만지지 않고 양식을 제출하려고하면 유효성 검사 오류가 표시되지 않는다는 것입니다. 컨트롤러에 해당 코드에 대한 자리 표시자가 있습니다.
내 생각은 간단합니다.

  1. 사용자가 제출 버튼을 클릭
  2. 모든 필드는 터치로 표시됩니다.
  3. 오류 포맷터가 다시 실행되고 유효성 검사 오류를 표시합니다.

누군가가 새로운 방법을 구현하지 않고 제출시 오류를 표시하는 방법을 알고 있다면 공유하십시오. 감사!


내 단순화 된 양식 :

<form class="form-horizontal" [formGroup]="form" (ngSubmit)="onSubmit(form.value)">
    <input type="text" id="title" class="form-control" formControlName="title">
    <span class="help-block" *ngIf="formErrors.title">{{ formErrors.title }}</span>
    <button>Submit</button>
</form>

그리고 내 컨트롤러 :

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

@Component({
  selector   : 'pastebin-root',
  templateUrl: './app.component.html',
  styleUrls  : ['./app.component.css']
})
export class AppComponent implements OnInit {
  form: FormGroup;
  formErrors = {
    'title': ''
  };
  validationMessages = {
    'title': {
      'required': 'Title is required.'
    }
  };

  constructor(private fb: FormBuilder) {
  }

  ngOnInit(): void {
    this.buildForm();
  }

  onSubmit(form: any): void {
    // somehow touch all elements so onValueChanged will generate correct error messages

    this.onValueChanged();
    if (this.form.valid) {
      console.log(form);
    }
  }

  buildForm(): void {
    this.form = this.fb.group({
      'title': ['', Validators.required]
    });
    this.form.valueChanges
      .subscribe(data => this.onValueChanged(data));
  }

  onValueChanged(data?: any) {
    if (!this.form) {
      return;
    }

    const form = this.form;

    for (const field in this.formErrors) {
      if (!this.formErrors.hasOwnProperty(field)) {
        continue;
      }

      // clear previous error message (if any)
      this.formErrors[field] = '';
      const control = form.get(field);
      if (control && control.touched && !control.valid) {
        const messages = this.validationMessages[field];
        for (const key in control.errors) {
          if (!control.errors.hasOwnProperty(key)) {
            continue;
          }
          this.formErrors[field] += messages[key] + ' ';
        }
      }
    }
  }
}



답변

다음 함수는 양식 그룹의 컨트롤을 반복하여 부드럽게 터치합니다. 컨트롤 필드가 객체이기 때문에 코드는 양식 그룹의 컨트롤 필드에서 Object.values ​​()를 호출합니다.

  /**
   * Marks all controls in a form group as touched
   * @param formGroup - The form group to touch
   */
  private markFormGroupTouched(formGroup: FormGroup) {
    (<any>Object).values(formGroup.controls).forEach(control => {
      control.markAsTouched();

      if (control.controls) {
        this.markFormGroupTouched(control);
      }
    });
  }


답변

에서 각도 8/9 당신은 간단하게 사용할 수 있습니다

this.form.markAllAsTouched();

컨트롤 및 하위 컨트롤을 터치로 표시합니다.

AbstractControl 문서


답변

@masterwork의 답변에 관해서. 이 솔루션을 시도했지만이 줄에서 FormGroup 대신 FormControl 인수를 전달하기 때문에 함수가 FormGroup 내부에서 재귀 적으로 파기하려고 할 때 오류가 발생했습니다.

control.controls.forEach(c => this.markFormGroupTouched(c));

여기 내 해결책이 있습니다.

markFormGroupTouched(formGroup: FormGroup) {
 (<any>Object).values(formGroup.controls).forEach(control => {
   if (control.controls) { // control is a FormGroup
     markFormGroupTouched(control);
   } else { // control is a FormControl
     control.markAsTouched();
   }
 });
}


답변

Angular v8에서는 markAllAsTouched메서드 의 도움으로이 기능이 내장되어 있습니다.

예를 들어 다음과 같이 사용할 수 있습니다.

form.markAllAsTouched();

공식 문서 참조 : https://angular.io/api/forms/AbstractControl#markallastouched


답변

양식 컨트롤을 반복하고 터치 한 것으로 표시하는 것도 작동합니다.

for(let i in this.form.controls)
    this.form.controls[i].markAsTouched();


답변

이것은 내 해결책입니다

      static markFormGroupTouched (FormControls: { [key: string]: AbstractControl } | AbstractControl[]): void {
        const markFormGroupTouchedRecursive = (controls: { [key: string]: AbstractControl } | AbstractControl[]): void => {
          _.forOwn(controls, (c, controlKey) => {
            if (c instanceof FormGroup || c instanceof FormArray) {
              markFormGroupTouchedRecursive(c.controls);
            } else {
              c.markAsTouched();
            }
          });
        };
        markFormGroupTouchedRecursive(FormControls);
      }


답변

나는이 문제가 있었지만 내가 발견 한 Angular 튜토리얼이 아니었지만 “올바른”방법을 찾았다.

HTML의 form태그 #myVariable='ngForm'에서 반응 양식 예제에서 사용하는 것 외에도 템플릿 기반 양식 예제에서 사용 하는 것과 동일한 템플릿 참조 변수 ( ‘hashtag’변수)를 추가합니다.

<form [formGroup]="myFormGroup" #myForm="ngForm" (ngSubmit)="submit()">

이제 다음 myForm.submitted대신 (또는 추가하여) 사용할 수있는 템플릿에 액세스 할 수 있습니다 myFormGroup.controls.X.touched.

<div *ngIf="myForm.submitted" class="text-error">
<span *ngIf="myFormGroup.controls.myFieldX.errors?.badDate">invalid date format</span>
<span *ngIf="myFormGroup.controls.myFieldX.errors?.isPastDate">date cannot be in the past.</span>
</div>

myForm.form === myFormGroup="ngForm"부분을 잊지 않는 한 그게 사실임을 알아라 . #myForm단독으로 사용하는 경우 var가 해당 요소를 구동하는 Directive 대신 HtmlElement로 설정되므로 작동하지 않습니다.

그것이 알고 myFormGroup반응 양식 자습서 당 구성 요소의 타이프 코드에서 볼 수 있지만, myForm당신은 같은 메소드 호출을 통해 그것을 통과하지 않는 한, 아니다 submit(myForm)submit(myForm: NgForm): void {...}. (알림 NgForm은 타이프 스크립트의 제목 대문자이지만 HTML의 경우 카멜 케이스입니다.)