Пользовательский валидатор в Angular Reactive Form не срабатывает

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

Это блок кода, в котором я добавляю элемент управления формой и валидатор.

`

var newdate = new Date();
this.dynamicForm.addControl(control.name, this.formBuilder.control(control.value, this.beforeDateValidator(newdate)));

`

А вот так выглядит валидатор...

`

    beforeDateValidator(dateValue: Date): ValidatorFn {
        console.info('im firing');

        return(control: AbstractControl) : ValidationErrors | null => {
            const value: Date = control.value;
            // console.info(value);
    
            if (!value) {
                return null;
            }

            if (dateValue=== null) {
                return null;
            }

            if (value < dateValue) {
                return { beforeDateValidator: 'Invalid Date' }
            } else {
                return null;
            } 
        }
    
    }

`

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

Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Angular и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
0
0
206
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Похоже, вы пытаетесь создать новый FormControl с тем же именем, что и уже существующий this.dynamicForm.addControl(control.name .....

Решение 1. Вы можете изменить использование addValidator на оставшийся элемент управления вместо создания нового.

this.form.controls["dynamicForm"].addValidators([this.beforeDateValidator(newdate)]);

Решение 2. Создайте новый с несуществующим именем.

.тс

Object.keys(this.dynamicForm.controls).forEach((control) => {
  this.dynamicForm.addControl(
    control + 'a',
    formBuilder.control('', [this.beforeDateValidator(newdate)])
  );
});

.html — убедитесь, что formControlName также содержит правильное имя.

<form [formGroup] = "dynamicForm" (ngSubmit) = "onSubmit()">
  <label for = "first-name">First Name: </label>
  <input id = "first-name" type = "text" formControlName = "control1a" />

  <label for = "last-name">Last Name: </label>
  <input id = "last-name" type = "text" formControlName = "control2a" />

  <button type = "submit">Submit</button>
</form>

пример: Stackblitz

Я так не думаю... Я проверил форму, и она создана правильно. Я не знаю почему... но я внес некоторые изменения в ваш пример, и он не срабатывает, когда тип ввода - дата. stackblitz.com/edit/angular-qzbu4u-mb3fcr?file=src/app/…

shine-dev 28.11.2022 05:58
Ответ принят как подходящий

Пользовательский валидатор будет запущен, но проблема в том, что control.value возвращает значение string, и вы сравниваете его со значением Date. Следовательно, это приводит к неожиданному значению, что ошибка не возвращается, которое используется для присвоения ошибки элементу управления формы.

Поместите console.info(), как показано ниже, и вы обнаружите, что он печатается как string.

console.info(typeof value);

Следовательно, перед сравнением убедитесь, что вам нужно преобразовать тип control.value в Date:

if (new Date(value) < dateValue) {
  ...
}

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

Вам необходимо отформатировать дату из ISOString в формат «гггг-мм-дд», как показано ниже:

import { formatDate } from '@angular/common';

this.dynamicForm.addControl(
  control.name,
  this.formBuilder.control('', this.beforeDateValidator(newdate))
);

this.dynamicForm.controls[control.name].patchValue(
  formatDate(control.value, 'yyyy-MM-dd', 'en')
);

Демо @ StackBlitz

Спасибо .. но я не знаю, решит ли это проблему. Я просто записываю строку в консоль каждый раз, когда нажимаю на средство выбора даты, и ничего не получаю. Я вижу валидатор в свойстве rawvalidators самого элемента управления... но после загрузки страницы... по какой-то причине он не срабатывает, когда я нажимаю на средство выбора даты и выбираю дату.

shine-dev 28.11.2022 17:25

Я думаю, что еще одна вещь, которую я должен упомянуть, это то, что... этот элемент формы не отображается, пока пользователь не выберет что-то ранее в форме. Влияет ли это на то, как срабатывает валидатор или нет?

shine-dev 28.11.2022 20:03

Да.. Я провел некоторое тестирование, и оказалось, что если я отрисовываю средство выбора даты при загрузке формы... все в порядке. но если какое-то другое событие вызывает отображение даты... тогда валидатор не работает должным образом.

shine-dev 28.11.2022 20:12

Я думаю, будет здорово, если вы сможете создать минимальный воспроизводимый пример в StackBlitz. Таким образом, мы можем узнать фактический код из вашего и выполнить отладку. Спасибо.

Yong Shun 29.11.2022 00:23

хм, лол ... поэтому я создал stackblitz остальной части моего кода и удалил большую часть материала ... и это сработало, как ваш ответ. Проблема была где-то еще в коде, валидатор удалялся, и я пропустил это :/ ... спасибо за указатель!

shine-dev 29.11.2022 07:59
stackblitz.com/edit/angular-empty-project-uuimqq?file=app/… Посмотрите этот stackblitz. Проблема, с которой я столкнулся... Я не могу передать значение даты, которую я хочу сравнить, с валидатором... и валидатор не срабатывает, когда я меняю дату на предыдущую дату. Он срабатывает только тогда, когда я меняю дату, которую нужно сравнить с предыдущей датой. Чтобы отображались даты... установите любой из флажков.
shine-dev 29.11.2022 17:42

Проблема в том, что ваш текущий способ установить валидатор на управление afterdate с первым временным значением beforedate. Таким образом, валидатор afterdate работает некорректно при изменении beforedate. Из моего [Demo[(stackblitz.com/edit/angular-empty-project-ch1spf?file‌​=app/…) я подписался на afterdate valueChanges элемента управления и переназначил валидатор на основе текущего выбранного beforedate ценить. Я думаю, что это один из способов удовлетворить ваше требование. Также исправлен ваш существующий код, который будет получать ошибку из-за отсутствия элемента управления beforedate.

Yong Shun 30.11.2022 02:53

Это хороший прогресс! Спасибо. Единственная проблема в том, что... она срабатывает только тогда, когда вы сначала устанавливаете дату до, а затем устанавливаете дату после. Если вы сначала установите дату после... а затем измените дату до, чтобы она произошла в будущем... это не вызовет пользовательский валидатор. Возможно, мы подписываемся и на предыдущую дату?

shine-dev 30.11.2022 18:02

Да, на самом деле зависит от вашего варианта использования. Если это то, что вы хотите, вам нужно подписаться на событие valueChange для элемента управления beforedate и обновить (сбросить) валидатор, передав текущее выбранное значение beforedate.

Yong Shun 01.12.2022 00:50

После того, как я подпишусь на предыдущую дату... мне обновить валидатор ?? или мне просто так звонить?? .. Я также не хочу называть это новым значением, потому что оно использует контрольное значение даты до... вместо контрольной даты "после даты". Либо так, либо напишите два разных валидатора.. для «недействительной даты после даты» и «валидатора до даты»

shine-dev 02.12.2022 03:39

Другие вопросы по теме

Как сохранить данные в массиве форм при редактировании другого элемента управления формой в Angular
Делить реактивную форму между компонентами
Заполнить реактивную форму датой, полученной из хранилища ngrx
Как в реактивных формах создать собственный валидатор, который может проверять массив formGroup на отсутствие значений?
Прокрутите вложенную группу форм и измените каждое значение элемента управления формы на нулевое, если оно имеет ошибку шаблона
Невозможно передать входное значение из представления в компонент с помощью #input
Как я могу восстановить значение поля формы ввода во вложенной форме
Как сбросить реактивную форму Angular без очистки предварительно заполненных данных?
Как создать входной фильтр для угловой таблицы?
Angular: сделать значения формы только для чтения серыми, а средство получения данных действительным с помощью Typescript