Цикл через вложенную группу форм и измените каждое значение элемента управления формой на null, если оно содержит ошибку шаблона

#angular #angular-reactive-forms

#angular #angular-reactive-forms

Вопрос:

Я должен найти, имеет ли один из моих formcontrols ошибку шаблона. Если у него есть ошибка шаблона, тогда я должен изменить значение этого formcontrol на null.

Я написал рекурсивный метод, который вызывает сам себя, чтобы проверить, имеет ли элемент управления формой ошибку шаблона, а затем он, наконец, возвращает true или false, но я хочу изменить значение этого formcontrol на null

Вот моя рекурсивная функция,

 hasPatternError(form: AbstractControl, isRecursion = false): boolean {
        if (!isRecursion) {
            this.patternErrors = [];
        }
        if (form instanceof FormControl) {
            return form.hasError('pattern') === true ?? null;
        }
        if (form instanceof FormArray) {
            form?.controls?.forEach(e => {
                this.hasAnyPatternError(e, true);
            });
        }
        if (form instanceof FormGroup) {
            Object.keys(form.controls).forEach(key => {
                const error = this.hasAnyPatternError(form.get(key), true);
                if (error === true) {
                    this.patternErrors.push(error);
                }
            });
            return this.patternErrors.length > 0 ? true : false;
        }
}
 

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

Примечание: я хочу, чтобы метод (hasPatternError) возвращал объект (с ошибкой, преобразованной в null, и не ожидал, что форма изменится в реальном времени)

 ngOnInit() {
    this.myForm = this.fb.group({
      name: [''],
      address: this.fb.group({
        street: [''],
        zip: [''],
        licenseNo: ['', [Validators.required, Validators.pattern(/^[a-z0-9]{10}$/i)]],
      })
    })
    this.myForm.valueChanges.subscribe(
      data => {
        console.log(this.hasAnyPatternError(this.myForm))
      }
    );
  }
 

Вот мой код на stackblitz

Комментарии:

1. Похоже, что самый простой способ решить эту проблему — иметь в вашем средстве проверки шаблонов массив, который хранит фактические элементы управления, соответствующие условию, и возвращает это. Затем вы можете просто перебрать этот массив элементов управления и выполнить для них setValue (null)?

2. @MikeOne Не могли бы вы показать мне, как использовать приведенный выше stackblitz?

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

4. У меня сложная вложенная группа форм с массивом форм

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

Ответ №1:

У вас уже есть ссылка на form элемент управления и элемент управления key , когда вы нажимаете на ошибку.

Установите значение для элемента управления в это время.

  • Поскольку вы делаете это с помощью рекурсии, кажется, что у него какое-то странное поведение, когда я играл с ним в вашем стекблите.
  • Но я хотел подчеркнуть, что для этого в элементе управления есть setValue функция, просто нужно определить наилучший способ ее использования в вашей логике.
  • Возможно, даже потребуется изучить отмену поведения и т. Д., Чтобы предоставить пользователю время для завершения нажатия клавиш.

 if (!form.controls[key]['controls'] amp;amp; error === true) {
                    setTimeout(()=>{
                      form.controls[key].setValue('');
                    },3000)
                    this.patternErrors.push(error);
                }
 

Я добавил a setTimeout , чтобы подождать 3 секунды, прежде чем снова установить значение '' для имитации отмены… похоже, это работает, но это неправильное решение, просто иллюстрирует принцип, который вам нужно изучить, чтобы setValue правильно использовать в вашей рекурсии.

STACKBLITZ

https://stackblitz.com/edit/ng-nested-formgroup-zet7ry?file=src/app/app.component.ts

Комментарии:

1. Спасибо за ваше время маршала. Я хочу, чтобы метод возвращал объект (с ошибкой, преобразованной в null, и не ожидал, что форма изменится в реальном времени). Поддержал ваш вопрос.

2. Извините, я, должно быть, неправильно понял второе предложение вашего сообщения.

Ответ №2:

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

 findPatternErrors(formItem: AbstractControl): FormControl[] {
  if (formItem instanceof FormControl) {
    if (formItem.hasError('pattern')) {
      return [formItem];
    } 
    return [];
  } 

  if (formItem instanceof FormArray) {
    const patternErrors: FormControl[] = [];
    formItem.controls?.forEach(arrayItem => {
      const ctrls = this.findPatternErrors(arrayItem);
      Array.prototype.push.apply(patternErrors, ctrls);
    });
    return patternErrors;
  }

  if (formItem instanceof FormGroup) {
    const patternErrors: FormControl[] = [];
    Object.keys(formItem.controls).forEach(key => {
      const ctrls = this.findPatternErrors(formItem.get(key));
      if (ctrls.length) {
        Array.prototype.push.apply(patternErrors, ctrls);
      }
    });
    return patternErrors;
  }
}
 

https://stackblitz.com/edit/ng-nested-formgroup-fmhfcs?file=src/app/app.component.ts

Комментарии:

1. Я знаю, как собрать элемент управления формой, который имеет ошибку, но моя конечная цель — иметь объект, значение которого formcontrol преобразовано в null.

2. В вашем примере, как я могу использовать массив patternErrors, который возвращает ваш метод, чтобы делать то, что я хочу?

3. patternErrors.forEach(ctrl => ctrl.reset());

4. О, да, круто. Как я об этом не знал? Спасибо, но зачем нам нужны номера строк 44 и 45 (вы нажимаете ctrl на patternErrors)? Потому что мы уже отправляем ctrl в строке с номером 55

5. Это основано на вашем коде. Разные if условия.