Я работаю с динамической реактивной формой, которая принимает ввод 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;
}
}
}
`
Проблема в том, что... валидатор не срабатывает, когда пользователь выбирает правильные значения и вводит значение даты, которое должно вызвать сообщение о недопустимой дате.
Похоже, вы пытаетесь создать новый 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
Пользовательский валидатор будет запущен, но проблема в том, что 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')
);
Спасибо .. но я не знаю, решит ли это проблему. Я просто записываю строку в консоль каждый раз, когда нажимаю на средство выбора даты, и ничего не получаю. Я вижу валидатор в свойстве rawvalidators самого элемента управления... но после загрузки страницы... по какой-то причине он не срабатывает, когда я нажимаю на средство выбора даты и выбираю дату.
Я думаю, что еще одна вещь, которую я должен упомянуть, это то, что... этот элемент формы не отображается, пока пользователь не выберет что-то ранее в форме. Влияет ли это на то, как срабатывает валидатор или нет?
Да.. Я провел некоторое тестирование, и оказалось, что если я отрисовываю средство выбора даты при загрузке формы... все в порядке. но если какое-то другое событие вызывает отображение даты... тогда валидатор не работает должным образом.
Я думаю, будет здорово, если вы сможете создать минимальный воспроизводимый пример в StackBlitz. Таким образом, мы можем узнать фактический код из вашего и выполнить отладку. Спасибо.
хм, лол ... поэтому я создал stackblitz остальной части моего кода и удалил большую часть материала ... и это сработало, как ваш ответ. Проблема была где-то еще в коде, валидатор удалялся, и я пропустил это :/ ... спасибо за указатель!
Проблема в том, что ваш текущий способ установить валидатор на управление afterdate
с первым временным значением beforedate
. Таким образом, валидатор afterdate
работает некорректно при изменении beforedate
. Из моего [Demo[(stackblitz.com/edit/angular-empty-project-ch1spf?file=app/…) я подписался на afterdate
valueChanges элемента управления и переназначил валидатор на основе текущего выбранного beforedate
ценить. Я думаю, что это один из способов удовлетворить ваше требование. Также исправлен ваш существующий код, который будет получать ошибку из-за отсутствия элемента управления beforedate
.
Это хороший прогресс! Спасибо. Единственная проблема в том, что... она срабатывает только тогда, когда вы сначала устанавливаете дату до, а затем устанавливаете дату после. Если вы сначала установите дату после... а затем измените дату до, чтобы она произошла в будущем... это не вызовет пользовательский валидатор. Возможно, мы подписываемся и на предыдущую дату?
Да, на самом деле зависит от вашего варианта использования. Если это то, что вы хотите, вам нужно подписаться на событие valueChange для элемента управления beforedate
и обновить (сбросить) валидатор, передав текущее выбранное значение beforedate
.
После того, как я подпишусь на предыдущую дату... мне обновить валидатор ?? или мне просто так звонить?? .. Я также не хочу называть это новым значением, потому что оно использует контрольное значение даты до... вместо контрольной даты "после даты". Либо так, либо напишите два разных валидатора.. для «недействительной даты после даты» и «валидатора до даты»
Я так не думаю... Я проверил форму, и она создана правильно. Я не знаю почему... но я внес некоторые изменения в ваш пример, и он не срабатывает, когда тип ввода - дата. stackblitz.com/edit/angular-qzbu4u-mb3fcr?file=src/app/…