Проверка угловой реактивной формы: выражение изменилось после проверки

#angular #angular-reactive-forms

#angular #угловые реактивные формы

Вопрос:

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

Если я инициирую какое-либо изменение, например, установив флажок в своей форме, то форма помечается как недействительная, пока я не введу значение в свой пользовательский элемент управления.

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

Таким образом, проблема возникает ТОЛЬКО при первой загрузке формы на экран.

Я заметил следующее исключение в консоли:

введите описание изображения здесь

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

Ниже приведен код моего пользовательского элемента управления. Я делаю что-то не так?

 import { Component, forwardRef, Input, OnInit, Output } from '@angular/core';
import { ControlValueAccessor, FormControl, NG_VALIDATORS, NG_VALUE_ACCESSOR } from '@angular/forms';
@Component({
  selector: 'app-multiple-checkbox',
  templateUrl: './multiple-checkbox.component.html',
  styleUrls: ['./multiple-checkbox.component.scss'],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => MultipleCheckboxComponent),
      multi: true
    },
    {
      provide: NG_VALIDATORS,
      useExisting: forwardRef(() => MultipleCheckboxComponent),
      multi: true
    }]
})
export class MultipleCheckboxComponent implements OnInit, ControlValueAccessor {

  value = [];
  disabled = false;

  @Input() public options: { key, value }[];

  onTouched: any;
  onChange: any;


  constructor() { }

  validate({ value }: FormControl) {
   
    const isNotValid = this.value.length === 0;
    return isNotValid amp;amp; {
      invalid: true
    };
  }

  ngOnInit(): void { }

  evaluate(event, key): void {
    if (event.target.checked) {
      this.value.push(key);
    } else {
      this.value.splice(this.value.findIndex(i => key === i), 1);
    }

    this.onChange(this.value);
    this.onTouched();
  }

  isChecked(key): boolean {
    return this.value.findIndex(e => e === key) > -1;
  }

  writeValue(value: any): void {
    this.value = value;
  }
  registerOnChange(fn: any): void {
    this.onChange = fn;
  }
  registerOnTouched(fn: any): void {
    this.onTouched = fn;
  }
  setDisabledState?(isDisabled: boolean): void {
    this.disabled = isDisabled;
  }

}
 

[ПРАВИТЬ]
Добавление способа добавления пользовательского элемента управления на экран в его родительской форме:

 <div [formGroup]="form">
 <div *ngIf="control.visible">

    <div [ngSwitch]="control.controlType">

        <div *ngSwitchCase="'checkbox'">
            <label [attr.for]="control.key">{{control.label}}</label>

            <input [formControlName]="control.key" [id]="control.key" type="checkbox"
                (change)="evaluate(control.key)">
        </div>

<!--  THIS IS MY CUSTOM CONTROL -->

        <app-multiple-checkbox *ngSwitchCase="'multipleCheckbox'" [formControlName]="control.key"
            [options]="control.options" (change)="evaluate(control.key)">
        </app-multiple-checkbox>
    </div>
</div>
 

[ПРАВИТЬ]

Следующий комментарий ниже, ошибка вызвана этой строкой в моей форме :

 <button type="submit" color="accent" (click)="save()" 
 [disabled]="catalogForm.invalid">Submit</button>
 

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

1. Можете ли вы создать stackblitz?

2. Не могли бы вы показать, как вы используете этот пользовательский компонент, например, как вы встраиваете его в свой шаблон? И как validate вызывается метод? Используете ли вы его с того места, ValidatorFn FormControl где используется этот компонент?

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

4. @Sam Для меня это выглядит нормально. В сообщении об ошибке, которое вы предоставили, что-то говорится об [disabled] атрибуте в catalog.component.html строке 11. Так что в основном любое выражение, которое вы там использовали, изменилось «слишком рано». В большинстве случаев, насколько я знаю, это происходит при изменении значения выражения внутри ngAfterViewInit .

5. на самом деле с реактивными формами более распространенным способом является подписка на valueChanges форму в файле ts вместо (change) обработчиков шаблонов. Я считаю, что это может решить вашу проблему

Ответ №1:

Выражение изменилось после проверки

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

Чтобы удалить эту ошибку в режиме разработки

 import ChangeDetectorRef from  @angular/core

constructor(private changeDecRef:ChangeDetectorRef) {}
 

затем

     if (event.target.checked) {
      this.value.push(key);
    } else {
      this.value.splice(this.value.findIndex(i => key === i), 1);
    }

    this.onChange(this.value);
    this.onTouched();

    /// ADD THIS FUNCTION ///
    this.changeDecRef.detectChanges();
  }```
 

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

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

2. это показывает, что в рабочем режиме что-то может пойти не так. так что вы не можете просто игнорировать это

3. Если я добавлю ваш код, ошибка все еще будет там, и моя проблема останется.

4. @sam вы должны добавить это в файл catalouge.component.ts..

5. Я тоже пробовал это, но тогда больше ничего не работает. FormControls больше не добавляются в форму.