Remove validation in angular 4 when it's not render in NgIf

Issue

I want to remove validation for which control is not rendered by using NgIf. I was try to use directive to remove with hidden control but cannot do the same because it not render in template. So I can not check formControlName with ElementRef in directive. Here is ts file

this.form = this._fb.group({
  text1: ['', Validators.required],
  text2:  ['', Validators.required]
});

and template

<form[formGroup]="form">
  <input type="text" formControlName="text1">
 <div *ngIf="false">
  <input type="text" formControlName="text2">
</div>

I want to remove Validation of text2 dynamically and globally. Not remove validator in ts file.

Solution

This Angular source GitHub Issue comment by Kara seems extremely relevant, and illustrates how you might solve the problem by treating the reactive model as “source of truth” and create your ngIf expression off of that source of truth, instead of the reverse. This shows it’s by design and you have to make some effort not to mix up template-driven and reactive form ideas.

https://github.com/angular/angular/issues/7970#issuecomment-228624899

Thanks for taking the time to describe the problem. I took a look at
your example code, and it seems that you are using the reactive form
directives (a.k.a “model-driven” directives: ngFormModel, etc), but a
template-driven strategy. The fact that the ngIf does not remove the
control from the form’s serialization and validation is actually by
design, and here’s why.

In each form paradigm – template-driven and reactive – there can only
be one source of truth for the list of active controls. In the
template-driven paradigm, the source of truth is the template. In the
reactive equivalent, the source of truth is the form model created in
the parent component. The DOM does not dictate the state of your form.
For this reason, if you remove form control elements from the DOM
while using a reactive approach, the form controls are not necessarily
changed in the source of truth unless you want them to be. You can
choose to update the controls imperatively by calling
this.form.removeControl(‘controlName’), or you can choose to keep the
controls in your form. This flexibility allows you to add or remove
inputs from the DOM temporarily while keeping their form values
serialized (e.g. if you have a number of collapsible sections to your
form, you can remove sections on collapse without impacting the value
of your form). We don’t want to restrict this flexibility and
complicate ownership by forcing the model to always match the DOM.

So in your case, if you choose a reactive strategy, you’ll want to
invert your logic to rely on the source of truth – the model.
Specifically, this means removing the control imperatively in the
model by calling this.form.removeControl(‘name’) when the button is
clicked. Then, the ngIf should depend on the control’s presence in the
model with *ngIf=”form.contains(‘name’)”, rather than the other way
around. See example plunker here:
http://plnkr.co/edit/V7bCFLSIEKTuxU9jcp6v?p=preview

It’s worth noting that if you’re still using beta.14 (as in your
plunker), you’ll need to call this.form.updateValueAndValidity()
manually. This requirement was removed in #9097, so versions after
RC.2 don’t require the call.

Another option is to convert to a template-driven strategy (no
ngFormModel), which will remove the control from the form when it’s
destroyed from the template. Example:
http://plnkr.co/edit/s9QWy9T8azQoTZKdm7uI?p=preview

I’m going to close this issue as it works as intended, but I think we
could make the experience a lot friendlier. A good start would be some
more cookbooks and guides in the documentation.

Answered By – MattTreichel

Answer Checked By – Candace Johnson (AngularFixing Volunteer)

Leave a Reply

Your email address will not be published.