使用组件Angular - TypeScript处理表单错误

Lye*_*UKH 24 html javascript typescript angular angular5

我目前正在处理几个字段(超过10个字段)的Angular/Typescript中的表单,我想更正确地管理错误而不重复我的html页面中的代码.

以下是表单的示例:

<form [formGroup]="myForm">
     <label>Name</label>
     <input type="text" formControlName="name">
     <p class="error_message" *ngIf="myForm.get('name').invalid && (myForm.submitted || myForm.get('name').dirty)">Please provide name</p>
     <label>Lastname</label>
     <input type="text" formControlName="lastname">
     <p class="error_message" *ngIf="myForm.get('lastname').invalid && (myForm.submitted || myForm.get('lastname').dirty)">Please provide email</p>
     <label>Email</label>
     <input type="text" formControlName="email">
     <p class="error_message" *ngIf="myForm.get('email').hasError('required') && (myForm.submitted || myForm.get('email').dirty)">Please provide email</p>
     <p class="error_message" *ngIf="myForm.get('email').hasError('email') && (myForm.submitted || myForm.get('email').dirty)">Please provide valid email</p>
</form>
Run Code Online (Sandbox Code Playgroud)

就我而言,我的表单有两种类型的验证:

  • Html验证:必需,maxSize,......等
  • 返回验证:例如,帐户无效,已加载文件的大小,...等.

我尝试使用这里提到的指令

<form [formGroup]="myForm">
     <label>Name</label>
     <input type="text" formControlName="name">
     <div invalidmessage="name">
        <p *invalidType="'required'">Please provide name</p>
     </div>
     <label>Lastname</label>
     <input type="text" formControlName="lastname">
     <div invalidmessage="lastname">
        <p *invalidType="'required'">Please provide lastname</p>
     </div>
     <label>Email</label>
     <input type="text" formControlName="email">
     <div invalidmessage="email">
        <p *invalidType="'required'">Please provide email</p>
        <p *invalidType="'email'">Please provide valid email</p>
     </div>
</form>
Run Code Online (Sandbox Code Playgroud)

但即使使用此解决方案,代码仍然是重复的,并且无法处理这两种类型的验证.

你有另一种方法吗?在这种情况下使用适当的组件吗?如果是,怎么办呢.

提前感谢您的投资.

Jay*_*ase 23

您可以将验证错误移动到组件中,并将formControl.errors作为输入属性传递.这样,所有验证消息都可以重复使用.这是StackBlitz的一个例子.代码使用的是Angular Material,但即使你不是,也应该很方便.

验证-errors.component.ts

import { Component, OnInit, Input, ChangeDetectionStrategy } from '@angular/core';
import { FormGroup, ValidationErrors } from '@angular/forms';

@Component({
  selector: 'validation-errors',
  templateUrl: './validation-errors.component.html',
  styleUrls: ['./validation-errors.component.css'],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class ValidationErrorsComponent implements OnInit {
  @Input() errors: ValidationErrors;

  constructor() {}

  ngOnInit() {}

}
Run Code Online (Sandbox Code Playgroud)

验证-errors.component.html

<ng-container *ngIf="errors && errors['required']"> Required</ng-container>
<ng-container *ngIf="errors && errors['notUnique']">Already exists</ng-container>
<ng-container *ngIf="errors && errors['email']">Please enter a valid email</ng-container>
Run Code Online (Sandbox Code Playgroud)

对于后验证消息,在表单控件上手动设置错误.

const nameControl = this.userForm.get('name');
nameControl.setErrors({
  "notUnique": true
});
Run Code Online (Sandbox Code Playgroud)

要在表单上使用验证组件:

   <form [formGroup]="userForm" (ngSubmit)="submit()">
      <mat-form-field>
        <input matInput placeholder="name" formControlName="name" required>
        <mat-error *ngIf="userForm.get('name').status === 'INVALID'">
          <validation-errors [errors]="userForm.get('name').errors"></validation-errors>      
        </mat-error>
      </mat-form-field>
      <mat-form-field>
        <input matInput placeholder="email" formControlName="email" required>
        <mat-error *ngIf="userForm.get('email').status === 'INVALID'">
          <validation-errors [errors]="userForm.get('email').errors"></validation-errors>
        </mat-error>
      </mat-form-field>
      <button mat-raised-button class="mat-raised-button" color="accent">SUBMIT</button>
    </form>
Run Code Online (Sandbox Code Playgroud)


pix*_*its 5

演示版

您可以通过自定义验证器组件来注入NgForm和访问FormControlName指令,@ContentChild以实现重用:

@Component({
  selector: '[validator]',
  template: `
    <ng-content></ng-content>
    <div *ngIf="formControl.invalid">
        <div *ngIf="formControl.errors.required && (form.submitted || formControl.dirty)">
             Please provide {{ formControl.name }}
        </div>
        <div *ngIf="formControl.errors.email && (form.submitted || formControl.dirty)">
             Please provide a valid email
        </div>
        <div *ngIf="formControl.errors.notstring && (form.submitted || formControl.dirty)">
             Invalid name
        </div>

    </div>
`})

export class ValidatorComponent implements OnInit {
   @ContentChild(FormControlName) formControl;
   constructor(private form: NgForm) { 

   }

   ngOnInit() { }

}
Run Code Online (Sandbox Code Playgroud)

要使用它,您将使用HTML元素包装所有表单控件(具有formControlName),并添加一个validator属性:

<form #f="ngForm" (ngSubmit)="onSubmit(f)" novalidate>
<div [formGroup]="myForm">
     <label>Name</label>
     <div validator>
         <input type="text" formControlName="name">
     </div>
     <label>Lastname</label>
     <div validator>
         <input type="text" formControlName="lastname">
     </div>
     <label>Email</label>
     <div validator>
         <input type="text" formControlName="email">
     </div>
</div>
<button type="submit">Submit</button>
</form>
Run Code Online (Sandbox Code Playgroud)

这将适用于同步和异步验证器。