angular / components

Component infrastructure and Material Design components for Angular
https://material.angular.io
MIT License
24.35k stars 6.74k forks source link

bug(MatDateRangeInput): validation fails to update if end date gets set to after start date #24075

Open alexschilpp opened 2 years ago

alexschilpp commented 2 years ago

Is this a regression?

The previous version in which this bug was not present was

No response

Description

When manually entering the start date to a date after the end date, you get a validation error "Invalid start date" which is correct and expected. However, if you correct the end date to a date that is after the start date the validation doesn't seem to update and still shows "Invalid start date".

Reproduction

https://stackblitz.com/run?file=src/app/date-range-picker-forms-example.ts https://stackblitz.com/edit/angular-ivy-a3ezpw?file=src/app/app.component.html

Steps to reproduce:

  1. Set start date to 12/1/2021 and end date to 12/2/2021
  2. Set start date to 12/3/2021
  3. Set end date to 12/4/2021

Expected Behavior

As soon as the end date is set to after the start date, validation should update and hide the error.

Actual Behavior

"invalid start date" error is still shown.

Environment

lekhmanrus commented 2 years ago

The link to the StackBlitz example is invalid. Probably it is not quite related to your issue, but you can use [min] and [max] inputs to limit users' input.

andrewseguin commented 2 years ago

Thanks for filing the issue - can you provide a working reproduction?

alexschilpp commented 2 years ago

Sorry, this one should work: https://stackblitz.com/edit/angular-ivy-a3ezpw?file=src/app/app.component.html

doll612 commented 2 years ago

I also getting similar issue with MatDateRange, when entering the date manually,

Showing an Invalid date.

Steps to reproduce:

  1. Set start Date 20/12/2021 and end date 21/12/2021 using the date picker
  2. Ent end Date 19/12/2021
  3. Enter start date 19/12/2021
Albert-Walner commented 2 years ago

This bug is related to: 21875

You can use this Workaround (Directive):

@Directive({
    selector: 'mat-date-range-input [sharedInputFix]'
})
export class SharedMatDateRangeInputFixDirective extends DestroyEmitterDirective() implements AfterContentInit, OnDestroy {
    @ContentChild(MatStartDate, { read: FormControlDirective })
    startDateControlDirective: FormControlDirective

    @ContentChild(MatEndDate, { read: FormControlDirective })
    endDateControlDirective: FormControlDirective

    ngAfterContentInit(): void {
        this.startDateControlDirective.valueChanges.pipe(distinctUntilChanged(), takeUntil(this.destroyed$)).subscribe(() =>
            setTimeout(() => {
                this.endDateControlDirective.control.updateValueAndValidity({
                    emitEvent: true,
                    onlySelf: false
                })
            })
        )
        this.endDateControlDirective.valueChanges.pipe(distinctUntilChanged(), takeUntil(this.destroyed$)).subscribe(() =>
            setTimeout(() => {
                this.startDateControlDirective.control.updateValueAndValidity({
                    emitEvent: true,
                    onlySelf: false
                })
            })
        )
    }
}

The setTimeout(...) is important... unfortunately.