angularangular-materialmat-datepicker

How to reuse the validation method written for mat datepicker in other components


In my component i have 2 date pickers and there is start date and end date validation . This method checks whether start date is before end date . This validation will be applicable for all the date pickers . How to reuse the validations in other components instead of writing the same logic again and again in other components.

searchOrder.ts

comparisonEnddateValidator(): any {
    let ldStartDate = this.formGroup.value['covstartdate'];
    let ldEndDate = this.formGroup.value['covenddate'];

    let startnew = new Date(ldStartDate);
    let endnew = new Date(ldEndDate);
    if (startnew > endnew) {
      return this.formGroup.controls['covenddate'].setErrors({ 'invaliddaterange': true });
    }

    let oldvalue = startnew;
    this.formGroup.controls['covstartdate'].reset();
    this.formGroup.controls['covstartdate'].patchValue(oldvalue);
    return this.formGroup.controls['covstartdate'].setErrors({ 'invaliddaterange': false });
  }

  comparisonStartdateValidator(): any {
    let ldStartDate = this.formGroup.value['covstartdate'];
    let ldEndDate = this.formGroup.value['covenddate'];

    let startnew = new Date(ldStartDate);
    let endnew = new Date(ldEndDate);
    if (startnew > endnew) {
      return this.formGroup.controls['covstartdate'].setErrors({ 'invaliddaterange': true });
    }

    let oldvalue = endnew;
    this.formGroup.controls['covenddate'].reset();
    this.formGroup.controls['covenddate'].patchValue(oldvalue);
    return this.formGroup.controls['covenddate'].setErrors({ 'invaliddaterange': false });
  }

searchOrder.html

<mat-form-field appearance="outline">
    <mat-label> Covering Start Date </mat-label>
    <input
      matInput
      [matDatepicker]="CovStartdate"
      formControlName="covstartdate"
      (dateChange)="comparisonStartdateValidator()"
      required
    />
    <mat-datepicker-toggle
      matSuffix
      [for]="CovStartdate"
    ></mat-datepicker-toggle>
    <mat-datepicker #CovStartdate></mat-datepicker>
    <mat-error
      *ngIf="
        formGroup.controls['covstartdate'].hasError('invaliddaterange')
      "
    >
      <strong>Start date cannot be greater than end date</strong>
    </mat-error>
    <mat-error
      *ngIf="formGroup.controls['covstartdate'].hasError('required')"
    >
      Covering Start date is <strong>required</strong>
    </mat-error>
  </mat-form-field>

  <mat-form-field appearance="outline">
    <mat-label> Covering End Date </mat-label>
    <input
      matInput
      [matDatepicker]="CovEnddate"
      formControlName="covenddate"
      (dateChange)="comparisonEnddateValidator()"
      required
    />
    <mat-datepicker-toggle
      matSuffix
      [for]="CovEnddate"
    ></mat-datepicker-toggle>
    <mat-datepicker #CovEnddate></mat-datepicker>
    <mat-error
      *ngIf="formGroup.controls['covenddate'].hasError('invaliddaterange')"
    >
      <strong>End date cannot be earlier than start date</strong>
    </mat-error>
    <mat-error
      *ngIf="formGroup.controls['covenddate'].hasError('required')"
    >
      Covering End date is <strong>required</strong>
    </mat-error>
  </mat-form-field>
</div>

Solution

  • Create a service. Then create a generic validator function that validates the date pickers.

    shared.service.ts

    comparisonEnddateValidator(formGroup, startControlName, endControlName): any {
        let ldStartDate = formGroup.value[startControlName];
        let ldEndDate = formGroup.value[endControlName];
    
        let startnew = new Date(ldStartDate);
        let endnew = new Date(ldEndDate);
        if (startnew > endnew) {
            formGroup.controls[endControlName].setErrors({
                invaliddaterange: true
            });
            return formGroup;
        }
    
        let oldvalue = startnew;
        formGroup.controls[startControlName].reset();
        formGroup.controls[startControlName].patchValue(oldvalue);
        formGroup.controls[startControlName].setErrors({
            invaliddaterange: false
        });
    
        return formGroup;
    }
    

    then call this function from your components -

    app.component.ts

    comparisonEnddateValidator(): any {
        this.formGroup = 
            this.sharedService.comparisonEnddateValidator(this.formGroup, 'covstartdate', 'covenddate');
        }
    }