0

I have an Angular form initialized with something like this

buildForm() {
    this.form = this.formBuilder.group({
        value1: this.formBuilder.control(null),
        value2: this.formBuilder.control(false)
    });
}

and I use a [required] in the tag in the html where I have two conditions, first is an object with a true/false required and the second being another value in the form (which can be updated in the ts or by a user).

<div [formGroup]="form">
    <div *ngIf="valuesObject.value1.display">
        <mat-form-field>
            <mat-select formControlName="value1"
                        [required]="valuesObject.value1.required || form.value.value2">
                <mat-option [value]="null"> empty <mat-option>
                <mat-option [value]="1"> option 1 <mat-option>
            </mat-select> 
        </mat-form-field>
    </div>
</div>

Every time the [required] flips from false -> true or true -> false, it sends an event to my form.valueChanges which then sends a call to the server because it thinks that data has been updated. Is there a way to ignore this event or capture it so I can set a flag to ignore it within the .valueChanges?

rhavelka
  • 2,283
  • 3
  • 22
  • 36

1 Answers1

2

If you use formControl, then you don't need to use the [required] attribute as well. Try to change your app logic in a way, that you use the formControl object to handle the required attribute - it's the proper way.

this.form.controls["value1"].setValidators([Validators.required]);

and to clear it

this.form.controls["value1"].clearValidators()

You need to update the form after this, to properly make the changes:

this.form.controls['value1'].updateValueAndValidity()

See this question

Update

As you said, the said check is quite frequent, and you whish to keep it in the template: in that case, I still suggest using a custom validator, in which you can encapsulate your logic.

See Cross field validation tutorial from the docs, for reactive forms (as you said you change the field's value from the code side too):

const heroForm = new FormGroup({
  'value1': new FormControl(),
  'value2': new FormControl()
}, { validators: myRequiredValidation });

export const : myRequiredValidation = (control: FormGroup): ValidationErrors | null => {
  const value1 = control.get('value1');
  const 'value2' = control.get('value2');

  return <your logic> ? { myRequiredValidation: true } : null;
};
ForestG
  • 17,538
  • 14
  • 52
  • 86
  • 1
    I am aware of this solution, but in my code I could have 10 places (which could increase in the future) that I am changing/checking when value1 (which could be in a parent component where my `valuesObject` doesn't exist) should be required/not required. plus I need to watch when value2 changes either by my logic (which I am ignoring most of those events) or by a user's events. having it in the html is easier for management and maintainability. – rhavelka Sep 21 '20 at 15:48
  • I see your point. I still respectfully disaggree with keeping validation logic in the template though: you can utilize custom validators to encapsulate your validation logic, and still use ony the formControl api. But I can understand if that's not what you are looking for, sadly I don't really know a good trick to go around this problem in any other way :( updated my answer with a custom validator option. – ForestG Sep 22 '20 at 07:11