0

There are two date inputs: d1 and d2.
The requirement is d2 must be greater than or equal to d1.

By default, the minimum date of d2 is 2018-09-03, which is stored in the minDate variable.

[A good case] If user inputs d1 first,
it will trigger the function onChange and update minDate to the value of d1. In this case, if user wants to update d2, all dates before minDate are disabled.

[A bad case] If user inputs d2 first,
and input d1 later with d1 > d2, I want the program to display an error msg by using the validation function settledateValidator. However, minDate passed to settledateValidator is not updated (still equals to its default value 2018-09-03 instead of the value of d1).

My questions:
1. why minDate does not get updated in [A bad case]? It is updated successfully in [A good case].
2. how to fix [A bad case]?

Thanks for your help in advance!

in .html:

<mat-form-field>
    <input matInput [matDatepicker]="picker_d1" placeholder="d1" [formControl]="d1" (dateChange)="onChange(d1)">
    <mat-datepicker-toggle matSuffix [for]="picker_d1"></mat-datepicker-toggle>
    <mat-datepicker #picker_d1 ></mat-datepicker>
</mat-form-field>

<mat-form-field>
    <input matInput [min]="minDate" [matDatepicker]="picker_d2" placeholder="d2" [formControl]="d2">
    <mat-datepicker-toggle matSuffix [for]="picker_d2" ></mat-datepicker-toggle>
    <mat-datepicker #picker_d2 > </mat-datepicker>
    <mat-hint *ngIf="!myform_fg.controls['d2'].valid"> d2 is smaller than d1 </mat-hint>
</mat-form-field>

in .ts:

function settledateValidator(min: Date): ValidatorFn {
  return (control: AbstractControl): { [key: string]: boolean } => {

    var sd = new Date(control.value);

    console.log(min);  //minDate does not change. it is still equal to its default value.

    if (sd < min){
      return {invalid_toosmall: true};
    }
  };
}

export class MyformComponent implements OnInit {

  minDate = new Date(2018, 8, 3);

  constructor(fb: FormBuilder) {

    this.myform_fg = fb.group({
      'd1': ['', Validators.compose([Validators.required])],
      'd2': ['', Validators.compose([Validators.required, settledateValidator(this.minDate)])],
    });

    this.d1 = this.myform_fg.controls['d1'];
    this.d2 = this.myform_fg.controls['d2'];

  }

  onChange(value: string): void {
    this.minDate = this.d1.value;
  }

}

1 Answer 1

1

You validators in initialize in the constructor and you give the "this.minDate". When this one change you change is reference but the validator to still have the old one.

I faced the case and a way to do what you want to do would be to give the reference to an object which never change like this to your validator :

//global
const minDateValid = { date : new Date(2018, 8, 3)};

//constructor
settledateValidator(minDateValid);

//on change
this.minDateValid.date = this.d1.value;

For more exemple, I personnaly do it by passing the formControl for exemple : (see minDateFromControl) https://github.com/xrobert35/asi-ngtools/blob/master/src/validators/asi-validators.ts

and make it work like this :

    this.myForm = fb.group({
      from: [null],
      to: [null]
    });

    this.myForm.controls.from.setValidators([Validators.required,
    AsiValidators.maxDateFromControl(this.myForm.controls.to)]);
    this.myForm.controls.to.setValidators([Validators.required,
    AsiValidators.minDateFromControl(this.myForm.controls.from)]);
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.