У вас включен AdBlock или иной блокировщик рекламы.

Пожалуйста, отключите его, доход от рекламы помогает развитию сайта и появлению новых статей.

Спасибо за понимание.

В другой раз
DevGang блог о програмировании
Авторизоваться

Проверка пользовательских форм в Angular 

В этой статье я расскажу, как создать кастомизатор из валидатора для приложений Angular и добавить этот валидатор в управляемые шаблоном формы или в реактивные формы.

Здесь я собираюсь продемонстрировать проверку поля ввода номера телефона, которое должно состоять из 10 цифр.

Вот два скриншота, которые иллюстрируют, как наша валидация будет выглядеть как пользовательский интерфейс:

Валидатор для шаблонной формы

Для проверки в формах на основе шаблонов используются директивы, поэтому давайте продолжим и создадим директиву phone-number-validator.

phone-number-validator.ts
import { Directive } from '@angular/core';
import { Validator, AbstractControl, NG_VALIDATORS } from '@angular/forms';

@Directive({
  selector: '[phoneValidateDirective]',
  providers: [{
    provide: NG_VALIDATORS,
    useExisting: AppPhoneValidateDirective,
    multi: true
  }]
})
export class AppPhoneValidateDirective implements Validator {
  validate(control: AbstractControl) : {[key: string]: any} | null {
    if (control.value && control.value.length != 10) {
      return { 'phoneNumberInvalid': true }; // return object if the validation is not passed.
    }
    return null; // return null if validation is passed.
  }
}

Не забудьте зарегистрировать и добавить валидатор в существующий массив валидаторов, предоставляемый Angular NG_VALIDATORS:

// ...
providers: [{
  provide: NG_VALIDATORS,
  useExisting: Your_Class_Name,
  multi: true
}]
// ...

Здесь я создал директиву валидации телефонного номера, которая реализует интерфейс Validator из @angular/forms, для которого мы должны предоставить следующий метод реализации: validate(control: AbstractControl): : {[key: string]: any} | null. Этот валидатор вернет объект, если валидация не пройдена, { 'phoneNumberInvalid': true } и null, если валидация пройдена.

Angular добавляет возвращаемое значение функции проверки в свойстве errors. Если свойство errors не пусто, то форма недействительна.

app.component.html
<div class="form-group col-sm-4">
  <label for="">Phone</label>
  <input type="text" class="form-control" name="phone" [(ngModel)]="phone" [class.is-invalid]="phonengModel.errors?.phoneNumberInvalid && (phonengModel.touched || phonengModel.dirty)" #phonengModel="ngModel" phoneValidateDirective>    <!-- Added directive to validate phone -->
  <span class="invalid-feedback" *ngIf="(phonengModel.touched || phonengModel.dirty) && phonengModel.errors?.phoneNumberInvalid"> <!-- Checked the errors property contains the 'phoneNumberInvalid' property or not which is returned by the validation function -->
      Phone number must be of 10 digit
  </span>
</div>

Валидатор для реактивных форм

Для проверки в Reactive Forms мы должны создать функцию.

app.component.ts
import { FormBuilder, AbstractControl } from '@angular/forms';
import { Component, OnInit } from "@angular/core";

@Component({
  selector: 'reactive-form',
  templateUrl: './reactive-form.component.html'
})
export class AppReactiveForm implements OnInit {
  myForm: FormGroup;

  constructor(
    private fb: FormBuilder
  ) {}

  ngOnInit() {
    this.myForm = this.fb.group({
      phone: ['', [ValidatePhone]] // added the function in validators array of form-control
    });
  }
}

function ValidatePhone(control: AbstractControl): {[key: string]: any} | null  {
  if (control.value && control.value.length != 10) {
    return { 'phoneNumberInvalid': true };
  }
  return null;
}

Мы добавляем функцию в массив валидаторов FormControl.

app.component.html
<form [formGroup]="myForm" novalidate class="needs-validation" (ngSubmit)="saveForm(myForm)">
  <div class="row">
    <div class="form-group col-sm-4">
      <label for="">Password</label>
      <input type="text" class="form-control " formControlName="phone" [class.is-invalid]="(myForm.get('phone').touched || myForm.get('phone').dirty) && myForm.get('password').">
      <span class="invalid-feedback" *ngIf="(myForm.get('password').touched || myForm.get('password').dirty) && myForm.get('password').invalid">
        Password is required
      </span> 
    </div>
  </div> 
</form>

Объединение обоих валидаторов

Мы можем объединить оба валидатора, чтобы не повторять наш код и следовать принципам DRY (не повторять себя):

phone-number-validator.ts
import { Directive } from '@angular/core';
import { Validator, AbstractControl, NG_VALIDATORS } from '@angular/forms';

export function ValidatePhone(control: AbstractControl): {[key: string]: any} | null  {
    if (control.value && control.value.length != 10) {
        return { 'phoneNumberInvalid': true };
    }
    return null;
}

@Directive({
    selector: '[phone]',
    providers: [{
        provide: NG_VALIDATORS,
        useExisting: AppPhoneValidateDirective,
        multi: true
    }]
})
export class AppPhoneValidateDirective implements Validator {
    validate(control: AbstractControl) : {[key: string]: any} | null {
    return ValidatePhone(control);
    }
}

Источник:

#Angular

Присоеденяйся в тусовку

Поделитесь своим опытом, расскажите о новом инструменте, библиотеке или фреймворке. Для этого не обязательно становится постоянным автором.

Попробовать