Как заставить поле в угловой реактивной форме повторно провести проверку - PullRequest
2 голосов
/ 30 сентября 2019

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

<div>
    Do you have any concerns?
</div>
<mat-radio-group formControlName="haveConcerns">
    <mat-radio-button [value]=true>yes</mat-radio-button>
    <mat-radio-button [value]=false>no</mat-radio-button>
</mat-radio-group>
<div [hidden]="!form.value.haveConcerns">
    <div>
        if "YES", please list the reasons:`enter code here`
    </div>
    <mat-form-field>
        <input formControlName="concerns" matInput placeholder="reasons" type="text">
        <mat-error *ngIf="hasError(this.form, 'concerns', 'maybeRequired')">
            please explain any concerns your may have
        </mat-error>
    </mat-form-field>
</div>

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

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

public applyForm(formValue) {
    this.formIsSubmitted = true;
    const concernsField= this.form.get('concerns');
    concernsField.setValue(concernsField.value);
    if (this.form.valid) {
        this.submitFormValue(formValue);
    }
}

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

1 Ответ

2 голосов
/ 01 октября 2019

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

this.form = this.fb.group({
  nested: this.fb.group(
    {
      haveConcerns: [false],
      concerns: [""]
    },
    { validators: concernValidator }
  )
});

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

ДЕМО ЗДЕСЬ

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

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


Если вы действительно хотите, чтобы валидатор был на concerns контроль формы, как вы заметили, вы должны каким-то образом запускать проверку на этом контроле формы при каждом изменении haveConcerns. Этого можно добиться, прослушивая valueChanges (или просто функцию, которая прослушивает изменение) для этого элемента управления формы и вызывая this.form.get('concerns).updateValueAndValidity(), что вызовет пользовательский валидатор для этого поля, например:

this.form.get("haveConcerns").valueChanges.subscribe(data => {
  this.form.get('concerns').updateValueAndValidity();
});

Если вы это сделаете, не забудьте отписаться от компонента OnDestroy

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