Угловая ошибка директивы при сбросе ключа - PullRequest
0 голосов
/ 28 июня 2019

Я пытался добавить проверку формы через директиву, которую я прикрепил к полю.Директива получает вызов по keyup и blur.В настоящее время, когда критерий ошибки удовлетворен, устанавливается ошибка, но я столкнулся с проблемой, при которой при вводе другого ключа сообщение об ошибке будет мигать (исчезать и появляться снова).

Просмотр элементов в консоли.Я вижу, что при нажатии клавиши Key (нажатие / удержание) моя директива еще не вызывается, но кое-как, как класс ngvalid добавляется к входу и сообщение об ошибке очищается.Отказ от ключа запускает мою директиву и сбрасывает ошибку.Я пробовал другую логику на ошибку переключения в HTML, но конечный результат тот же.Если бы я удалил слушатель keyup и строго запустил размытие, я получил бы похожий результат: введите неверное значение -> щелчок при вводе вызывает ошибку -> перефокусировка и нажатие клавиши приводит к исчезновению ошибки.

КомпонентHTML

<div [formGroup]="group">
    <label for="item?.keyName" class="input-label">{{item?.titleText}}</label>
    <input
        id="item?.keyName"
        name="name"
        type="text"
        data-id="textInput"
        [placeholder]="item?.placeHolder"
        zipCodeValidator
        [formControlName]="item?.keyName"
        required>

    <span [hidden]="!group.get(item?.keyName).dirty && !group.get(item?.keyName).errors?.zipCode">
          {{group.get(item?.keyName).errors?.zipCode}}
    </span>
</div>

Директива

import {Directive, HostListener} from '@angular/core';
import {AbstractControl, NgControl} from '@angular/forms';

@Directive({
    selector: '[zipCodeValidator]',
})

export class ZipCodeValidator {
    private regex: RegExp = new RegExp(/^(?:\d{5})?$/);
    private errorMessages = {
        badRegex: 'Enter a valid 5-digit US zip code. E.g. 48226.',
        emptyValue: 'Please enter a value.',
    };

    constructor(private control: NgControl) {}

    @HostListener('keyup')
    public onKeyUp(): void {
        this.validateZipCode();
    }

    @HostListener('blur')
    public onBlur(): void {
        this.validateZipCode();
    }

    private validateZipCode(): void {
        const formControl: AbstractControl = this.control.control;
        let errorMessage: string = null;

        if (!formControl.value) {
            errorMessage = this.errorMessages.emptyValue;
        }

        if (!this.regex.test(formControl.value)) {
            errorMessage = this.errorMessages.badRegex;
        }

        formControl.setErrors({ zipCode: errorMessage });
    }
}

Ожидаемый результат состоит в том, что при установке ошибки сообщение об ошибке должно оставаться и не очищаться никаким другим событием, кроме директивы.

Ответы [ 2 ]

1 голос
/ 28 июня 2019

Я понятия не имею, почему событие keyup вызывает такое поведение.Но использование события input вместо keyup даст вам желаемое поведение.

@HostListener('input')
public onKeyUp(): void {
    this.validateZipCode();
}

еще одна вещь;

validateZipCode() функция установит { zipCode: null } на formControl.erros, когдапочтовый индекс действителен.Однако это все равно приведет к тому, что formControl будет недействительным.validateZipCode() не должен устанавливать ничего, когда почтовый индекс действителен.

  private validateZipCode(): void {
    const formControl: AbstractControl = this.control.control;
    let errorMessage: string = null;

    if (!formControl.value) {
      errorMessage = this.errorMessages.emptyValue;
    }

    if (!this.regex.test(formControl.value)) {
      errorMessage = this.errorMessages.badRegex;
    }

    if (!errorMessage) return;

    /** if there are other errors we preserve them */
    if(formControl.errors)
      formControl.setErrors({...formControl.errors, zipCode: errorMessage });
    else
      formControl.setErrors({ zipCode: errorMessage });
  }

вот рабочая демоверсия https://stackblitz.com/edit/angular-ydsheq

Кроме того, я настоятельно рекомендую использовать Пользовательские валидаторы , который является угловым способом обработки формы, и он защитит вас от таких побочных эффектов.И это потребует меньше кода.Например,

  zipCodeValidator: ValidatorFn = (control: FormControl): ValidationErrors | null => {
    const regex: RegExp = new RegExp(/^(?:\d{5})?$/);
    if (!control.value) return { zipCode: "Please enter a value." };
    if(!regex.test(control.value)) return { zipCode: 'Enter a valid 5-digit US zip code. E.g. 48226.' };
    return null;
  }

  formCtrl = new FormControl("", [Validators.required, this.zipCodeValidator]);

вот рабочая демонстрация для валидаторов пользовательских форм https://stackblitz.com/edit/angular-u7xryz

0 голосов
/ 01 июля 2019

Так что я думаю, что нашел проблему. Таким образом, ручная установка ошибки с помощью директивы без фактического назначения валидатора приведет к удалению ошибки при изменении ввода, так как форма обновляется и угловые повторные проверки правильности. Установка валидатора и перемещение существующей логики валидации в этот метод решает проблему. Этот код может быть вызывающе очищен дальше, но я думаю, что это понятно. Так что @ysf был прав, когда рекомендовал использовать специальные валидаторы. Большое спасибо за помощь!

@Directive({
    selector: '[zipCodeValidator]',
})

export class ZipCodeValidator {
    constructor(private control: NgControl) {}

    @HostListener('keyup')
    public onKeyUp(): void {
        this.validateZipCode();
    }

    @HostListener('blur')
    public onBlur(): void {
        this.validateZipCode();
    }

    private validateZipCode(): void {
        const formControl: AbstractControl = this.control.control;
        formControl.setValidators([this.testVal]);
    }

    private testVal(control: AbstractControl): { [key: string]: string } | null {
        const regex: RegExp = new RegExp(/^(?:\d{5})?$/);
        const errorMessages = {
            badRegex: 'Enter a valid 5-digit US zip code. E.g. 48226.',
            emptyValue: 'Please enter a value.',
        };

        let errorMessage: string = null;

        if (!control.value) {
            errorMessage = errorMessages.emptyValue;
        }

        if (!regex.test(control.value)) {
            errorMessage = errorMessages.badRegex;
        }

        return { 'zipCode': errorMessage };
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...