如何在表单验证时在角度模板中显示<span>元素?

时间:2019-11-15 06:59:36

标签: javascript css angular typescript reactive

所以我正在做这个角度反应形式的项目,我有一个有趣的问题。 我的任务是在无效的每个表单输入下方显示一个跨度的验证错误。表单输入应在点击时进行验证,表单应在提交时进行验证。 我需要在outclick上呈现span元素,但同时,如果我从未在任何输入中输入任何内容并提交表单,则应该呈现相同的span。 因此,或者我输入了一些无效的内容,然后窗体用一个跨度告诉了我,或者单击了Submit按钮,窗体显示了每个无效输入的范围。 我希望以编程方式添加所有范围,但是通过模板也应该很好。 我的逻辑是将所有“错误”(基本上是每个跨度的内容)保存到数组中,并将所有状态保存到数组中,并通过循环和模板绑定显示它们。 我既无法弄清楚我的想法的逻辑,也无法弄清简单的解决方案。请帮助我。

我的模板:

<form class="form" [formGroup]="signUpForm" (ngSubmit)="onSubmit()">
    <div class="form__group form__group--name">
        <div class="form__control form__first-name">
            <input type="text" name="Fname" required formControlName="firstName" a-ngblur="onBlur(true)">
            <label>First Name</label>
        </div>
        <div class="form__control form__last-name">
            <input type="text" name="Lname" required formControlName="lastName">
            <label>Last Name</label>
        </div>
    </div>
    <div class="form__group form__group--id">
        <div class="form__control form__email">
            <input type="text" name="email" required formControlName="email">
            <label>Email ID</label>
        </div>
        <div class="form__control form__ID">
            <input type="text" name="ID" required formControlName="id">
            <label>Your User ID</label>
        </div>
    </div>
    <div class="form__group form__group--location form-group">
        <div class="form__control form__country">
            <span>Country</span>
            <select class="form-control" name="country" formControlName="country" (change)="onChange()" (click)="onOpen('country')">
                <option [value]="null" disabled>Choose your country</option>
                <option  *ngFor="let country of countries"  [value]="country.value">{{ country.value }}</option>
            </select>
        </div>
        <div class="form__control form__location">
            <div class="form__location--state" [ngSwitch]="this.signUpForm.get('country').value">
                <span>State</span>
                <select name="state" formControlName="state" *ngSwitchCase="'USA'">
                    <option [value]="null" disabled>Choose state</option>
                    <option *ngFor="let state of statesUSA"  [value]="state.value">{{ state.value }}</option>
                </select>
                <select name="state" formControlName="state" *ngSwitchCase="'India'">
                    <option [value]="null" disabled>Choose state</option>
                    <option *ngFor="let state of statesIndia"  [value]="state.value">{{ state.value }}</option>
                </select>
                <select name="state" formControlName="state" *ngSwitchCase="undefined">
                    <option [value]="null" disabled>Choose state</option>
                </select>
            </div>
            <div class="form__location--city" [ngSwitch]="this.signUpForm.get('state').value">  
                <span>City</span>
                <select name="city" formControlName="city" *ngSwitchCase="'New York'">
                    <option [value]="null" disabled>Choose city</option>
                    <option *ngFor="let city of citiesNY"  [value]="city.value">{{ city.value }}</option>
                </select>
                <select name="city" formControlName="city" *ngSwitchCase="'California'">
                    <option [value]="null" disabled>Choose city</option>
                    <option *ngFor="let city of citiesCali"  [value]="city.value">{{ city.value }}</option>
                </select>
                <select name="city" formControlName="city" *ngSwitchCase="'Andhra Pradesh'">
                    <option [value]="null" disabled>Choose city</option>
                    <option *ngFor="let city of citiesAndhra"  [value]="city.value">{{ city.value }}</option>
                </select>
                <select name="city" formControlName="city" *ngSwitchCase="'Goa'">
                    <option [value]="null" disabled>Choose city</option>
                    <option *ngFor="let city of citiesGoa"  [value]="city.value">{{ city.value }}</option>
                </select>
                <select name="city" formControlName="city" *ngSwitchCase="undefined">
                    <option [value]="null" disabled>Choose city</option>
                </select>
            </div>
        </div>
    </div>
    <div class="form__group form__control--data">
        <div class="form__control form__phone">
            <input type="text" name="phone" required formControlName="phone" #phoneInput
            [imask]="{mask: '+{38}(000)000-00-00'}" [unmask]="true">
            <label>Phone Number</label>
        </div>
        <div class="form__control form__code">
            <input type="text" name="code" class="ref-code" formControlName="code" style="text-transform: uppercase;">
            <label>Reference Code</label>
        </div>
    </div>
    <div class="form__group form__group--buttons">
        <a type="button" (click)="onReset()" class="form__group--buttons-reset">Reset All</a>
        <button type="submit" class="form__group--buttons-submit">Continue</button>
    </div>
</form>

我的TS:

import { Component, OnInit, ViewChild, ElementRef } from '@angular/core';
import { FormGroup, FormControl, FormArray, Validators } from '@angular/forms';
import { storageService } from '../storage-service.component';

@Component({
  selector: 'app-form',
  templateUrl: './form.component.html',
  styleUrls: ['./form.component.scss']
})
export class FormComponent implements OnInit {
  signUpForm: FormGroup;
  countries = [
    new FormControl('USA'),
    new FormControl('India')
  ];

  statesUSA = [new FormControl('New York'), new FormControl('California')];
  statesIndia = [new FormControl('Andhra Pradesh'), new FormControl('Goa')]

  citiesNY = [new FormControl('Albany'), new FormControl('New York City')];
  citiesCali = [new FormControl('Sacramento'), new FormControl('Los Angeles'), new FormControl('San Francisco')];
  citiesAndhra = [new FormControl('Visakhapatnam'), new FormControl('Amaravati')];
  citiesGoa = [new FormControl('Panaji'), new FormControl('Vasco da Gama')];

  @ViewChild('phoneInput', {static: false}) phoneInput: ElementRef;
  public mask:any = {
    mask: '+{38}(0__)000-00-00',
    lazy: false
  }

  invalidMessages = ['This field is required and has to contain 2-32 cyrillic characters!', 
  'This field is required and has to be a valid email address!',
  'This is a required field!',
  'This is a required field! Please enter your telephone number, formated as "0__-___-__-__"',
  'This field is required and has to contain 2-32 cyrillic characters',
  'This is a required field! It has to contain from 5 to 30 latin characters and "_"',
  'This is a required field!',
  'This is a required field!',
  'This field has to contain from 1 to 10 latin characters or numbers.'];

  public statusArr : string[] = [];

  constructor(private storageService: storageService) { }

  ngOnInit() {
    this.signUpForm = new FormGroup({
      'firstName': new FormControl(null, [Validators.required, Validators.pattern(/^[а-яА-ЯёЁіІїЇ]{2,32}$/iu)]),
      'email': new FormControl(null, [Validators.required, Validators.email, Validators.pattern(/^\S{2,255}@\S+\.\S+$/iu)]),
      'country': new FormControl(null, Validators.required),
      'phone': new FormControl(null),
      'lastName': new FormControl(null, [Validators.required, Validators.pattern(/^[а-яА-ЯёЁіІїЇ]{2,32}$/iu)]),
      'id': new FormControl(null, [Validators.required, Validators.pattern(/\b[A-Za-z_]{5,30}\b/)]),
      'state': new FormControl(null, Validators.required),
      'city': new FormControl(null, Validators.required),
      'code': new FormControl(null, [Validators.pattern(/\b[A-Za-z_0-9]{1,10}\b/)])
    });

    if(this.storageService.savedForm) this.signUpForm.setValue(this.storageService.savedForm);
  }

  onSubmit() {
    if(this.signUpForm.status === 'VALID') {
      this.storageService.savedForm = this.signUpForm.value;
      console.log(this.signUpForm);
    } else {
      let namesArr = Object.keys(this.signUpForm.controls);
      console.log(namesArr);
      for(let i = 0; i < namesArr.length; i++) {
        this.statusArr.push(this.signUpForm.controls[namesArr[i]].status);
      }
      console.log(this.statusArr);
    }
  }

  onReset() {

  }

  onChange() {
   (<FormGroup>this.signUpForm.get('state').value) = null;
   (<FormGroup>this.signUpForm.get('city').value) = null;
  }

  onOpen(controlName: string) {
  }
}

1 个答案:

答案 0 :(得分:1)

请尝试以下这种方法,我仅对一种表单控件进行了处理,如果可以的话,也可以对所有其他控件进行添加。 在HTML中

<div class="form__control form__first-name">
    <input type="text" name="Fname" required formControlName="firstName" a-ngblur="onBlur(true)">
    <label>First Name</label>
    <span *ngIf="firstname.errors.required && firstname.touched">This field is required</span>
    <span *ngIf="firstname.errors.pattern && firstname.touched">Pattern not matching</span>
</div>

在组件中,为所有窗体控件添加吸气剂。

get firstName(){
    this.signUpForm.get('firstName')
}

如果您不想编写吸气剂,则可以在模板中进行更改,例如

<span *ngIf="signupForm.get('firstname').errors.required && signupForm.get('firstname').touched">This field is required</span>

替换为脏污,仅在单击时显示错误(输入模糊)。

就提交而言,如果表单无效,则不允许用户提交表单(因为角度每次更改值后都会运行所有验证器),例如禁用按钮

<button [disabled]="signupForm.invalid">Submit form</button>