Предикат условной проверки реактивных форм вызывается только при загрузке страницы - PullRequest
0 голосов
/ 13 апреля 2020

Вот plnkr для моего вопроса: https://plnkr.co/edit/ObTq02rzcTdA6I2W

Важный код, на котором следует сосредоточиться:

this.formGroup = this.formBuilder.group({
  dropdown: [null, Validators.required],
  textbox: [null, requiredIf(() => this.formGroup.get('dropdown').value == "isRequired")]
});

saveButtonClick () {
  this.formGroup.updateValueAndValidity();
  console.log("form valid: " + this.formGroup.valid);
}

requiredIf (predicate) {
    return ((formControl) => {
        if (predicate()) {
            return Validators.required
        }
        return null;
    });
}

Если вы открываете консоль во время запустив пример кода, вы увидите, какие функции вызываются. Предикат, передаваемый requiredIf, вызывается только при изменении значения текстового поля. Я ожидал, что он будет вызван при изменении какого-либо поля или, по крайней мере, когда saveButtonClick () вызывает updateValueAndValidity (), но ничего из этого не происходит.

Как вызвать условную проверку, чтобы она была повторно оценена при нажатии кнопки сохранения нажата?

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

Ответы [ 2 ]

0 голосов
/ 14 апреля 2020

для меня хорошим подходом является отключение / включение элемента управления (когда FormControl отключен, всегда действует), см., Например, этот вопрос SO

В SO используется Флажок, внешний по отношению к форме, можно использовать, например,

<input formControlName="textbox" 
     [enabledControl]="form.get('dropdown').value=='isRequired'">

ПРИМЕЧАНИЕ. Если вы хотите скрыть ввод, НЕ используйте * ngIf используйте

[style.display]="form.get('dropdown').value=='isRequired'?'block':'none'
0 голосов
/ 14 апреля 2020

После некоторого тестирования я в конечном итоге обнаружил, что updateValueAndValidity, как я предполагал, не обновляет все элементы управления в форме и что путем перебора всех элементов управления и обновления каждого из них в отдельности мы можем достичь желаемого результата:

  recursivelyUpdateAndValidate(control) {
    if (control.controls) {
      Object.keys(control.controls).forEach(key => {
          this.recursivelyUpdateAndValidate(control.get(key));
        });
    }
    control.updateValueAndValidity();
  }

  saveButtonClick() {
      this.recursivelyUpdateAndValidate(this.formGroup);
      console.log("form valid: " + this.formGroup.valid);
    }
  }

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

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

this.formGroup = this.formBuilder.group({
  dropdown: [null, Validators.required],
  textbox: [null, textboxValidator],
  nested: this.formBuilder.group({
    anotherTextBox: [null, textboxValidator],
  })
});

Я оставлю этот вопрос открытым, если найдутся лучшие ответы.

...