1

I am using Angular 6 and Material form.

In a div there are 3 fields, 2 date picker and 1 input text field. We just need that if there is a value entered in a field then all should be mandatory.

The way I have tried is:

HTML

<div class="flex-container PromotionalPriceInfo">

    <span class="flex-item bold small">Promotional</span>

    <mat-form-field class="flex-item">

        <input matInput [matDatepicker]="promotionalPriceStartDatePicker" placeholder="Promotional Price Start Date" formControlName="promotionStartDate"
        />

        <mat-datepicker-toggle matSuffix [for]="promotionalPriceStartDatePicker"></mat-datepicker-toggle>

        <mat-datepicker #promotionalPriceStartDatePicker></mat-datepicker>

    </mat-form-field>

    <mat-form-field class="flex-item">

        <input matInput [matDatepicker]="promotionalPriceEndDatePicker" placeholder="Promotional Price End Date" formControlName="promotionEndDate"
        />

        <mat-datepicker-toggle matSuffix [for]="promotionalPriceEndDatePicker"></mat-datepicker-toggle>

        <mat-datepicker #promotionalPriceEndDatePicker></mat-datepicker>

    </mat-form-field>

    <mat-form-field class="flex-item">

        <input matInput type="number" placeholder="New Price" formControlName="promotionPrice" />

    </mat-form-field>

</div>

Component.ts onInit() I am setting a custom validator as :

this.storeServiceForm.get('promotionStartDate').setValidators(requiredPromotionalFields);

this.storeServiceForm.get('promotionEndDate').setValidators(requiredPromotionalFields);

this.storeServiceForm.get('promotionPrice').setValidators(requiredPromotionalFields);

Custom Validator code as:

export function requiredPromotionalFields(control: FormControl) {
    const promotionStartDate = control.parent.get('promotionStartDate').value;
    const promotionEndDate = control.parent.get('promotionEndDate').value;
    const promotionPrice = control.parent.get('promotionPrice').value;
    return ((!promotionStartDate && !promotionEndDate && !promotionPrice) || control.value) ? null : {
        required: true
    };
}

Which works fine if there is a value in any field while loading of page but it do not revalidate the other fields on change of value in any field

Which can be worked if I use below code as:

 this.storeServiceForm.get('promotionStartDate').valueChanges.subscribe(value => {
            this.storeServiceForm.controls['promotionStartDate'].updateValueAndValidity({ emitEvent: false });
            this.storeServiceForm.controls['promotionEndDate'].updateValueAndValidity();
            this.storeServiceForm.controls['promotionPrice'].updateValueAndValidity();
        });

        this.storeServiceForm.get('promotionEndDate').valueChanges.subscribe(value => {
            this.storeServiceForm.controls['promotionStartDate'].updateValueAndValidity();
            this.storeServiceForm.controls['promotionEndDate'].updateValueAndValidity({ emitEvent: false });
            this.storeServiceForm.controls['promotionPrice'].updateValueAndValidity();
        });

        this.storeServiceForm.get('promotionPrice').valueChanges.subscribe(value => {
            this.storeServiceForm.controls['promotionStartDate'].updateValueAndValidity();
            this.storeServiceForm.controls['promotionEndDate'].updateValueAndValidity();
            this.storeServiceForm.controls['promotionPrice'].updateValueAndValidity({ emitEvent: false });
        });    

But above code breaks down to error something like Maximum call stack size exceeded. Only for first time I change any value and then also only validation is working on price change not on other fields. And hang browser.

Can this be fixed, or is there any other way?

1

1 Answer 1

1

You need to add a parameter in your second updateValueValidity method, because you are subscribing to a value that you update. So infinite loop.

The parameter is {emitEvent: false;} https://angular.io/api/forms/AbstractControl#updateValueAndValidity

Sign up to request clarification or add additional context in comments.

3 Comments

I have changed subscribes as below : But for first time whatever value I enter in a field It goes in infinite loop , not from second time and validation is only working for price field change not on others:
Please provide a jsfiddle or something then
I have never used something like that , I have opened it but if I will paste too part of html and ts it will not able to run independently

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.