7

I'd like to enable/disable a button based on a datepicker, and I have a setup for a check like this:

  public dateChanged = false;
  public availableFromDate: Date;
  public availableToDate: Date;

 initDatepickers() {
    const currentDay = new Date();
    this.availableFromDate = currentDay;
    this.availableToDate = currentDay;
  }

 private dateCheck() {
    if ((this.availableFromDate > this.availableToDate) || (this.availableFromDate === this.availableToDate)) {
      this.dateChanged = false;
    } else {
      this.dateChanged = true;
    }
    console.log(this.dateChanged);
    console.log(`Available from - ${this.availableFromDate}`);
    console.log(`Available to - ${this.availableToDate}`);
  }

The check works good upwards, and enables the button when from date is lower, however! If you log the values to the console be button is disabled because the init value is false, not because the check works.

The two date objects are initialized differently (console.log dump):

true
clinics-upload-documents.component.ts:73 Available from - Fri Feb 22 2019 00:00:00 GMT+0100 (Central European Standard Time)
clinics-upload-documents.component.ts:74 Available to - Fri Feb 22 2019 10:52:31 GMT+0100 (Central European Standard Time)

It's never going to be false because the first date obj is @ 0:00:00 however the 2nd is tied to current local time.

these are used to manipulate the dates:

onFromChange(fromDate) {
  const dateType = 'from';
  this.setDateValues(fromDate, dateType);
}
onToChange(toDate) {
  const dateType = 'to';
  this.setDateValues(toDate, dateType);
}
private setDateValues(date: Date, dateType: string) {
  dateType === 'from' ? this.availableFromDate = new Date(date) : this.availableToDate = new Date(date);
  this.dateCheck();
}

What am I missing so badly?

Durga
  • 15,263
  • 2
  • 28
  • 52
Exitl0l
  • 459
  • 2
  • 11
  • 27

2 Answers2

3

Change this:

const currentDay = new Date();
this.availableFromDate = currentDay;
this.availableToDate = currentDay;

To this:

const currentDay = new Date();
currentDay.setHours(0, 0, 0, 0);
this.availableFromDate = new Date(currentDay);
this.availableToDate = new Date(currentDay);

This will zero out the time portion and make date comparison straight forward.

Next, change this:

if (
   (this.availableFromDate > this.availableToDate) ||
   (this.availableFromDate === this.availableToDate)
)

To this (assuming that you want to check greater than or equal to):

if (this.availableFromDate >= this.availableToDate)

You cannot compare two dates with === although you can compare them using < <= >= >.

Salman A
  • 262,204
  • 82
  • 430
  • 521
  • The issue still exists. `Available from - Fri Feb 22 2019 00:00:00 GMT+0100 (Central European Standard Time)` `Available to - Fri Feb 22 2019 00:36:13 GMT+0100 (Central European Standard Time)` I've added : `currentDay.setHours(0, 0, 0, 0);` But it still returns true however the two date objects should be equal – Exitl0l Feb 22 '19 at 10:37
  • Thanks the final edit helped the most! I've searched for date comparsion but i found that i can use ===. – Exitl0l Feb 22 '19 at 10:41
  • @Alex no. Just try this in console: `var a = new Date(); b = new Date(a); console.log(a === b); console.log(a.getTime() === b.getTime());` – Salman A Feb 22 '19 at 10:44
1

It looks like the Date objects that come in from your date picker via onFromChange/onToChange are pure dates (they are all at midnight), while the date objects that you create with Date() will have the current time included. The js Date class should really have been called DateTime. The mismatched times will cause the === comparison to fail.

Try using something like this to set availableFromDate and availableToDate in your initDatepickers function:

private getCurrentDate() {
    const date = new Date();
    date.setHours(0);
    date.setMinutes(0);
    date.setSeconds(0);
    date.setMilliseconds(0);
}

EDIT: Nevermind, the === will still fail if you do this, because Date is an object, so === checks for reference equality. Two Date objects can hold the same underlying date/time values, but they are still considered to be separate objects. Things like numbers, however, are value types, so === will tell you if the two values are equal. E.g:

5 === 5; // True, because pure numbers are value types
const number1 = { number: 5 }; // This is an object, so it is a reference type. Dates are also objects.
const number2 = { number: 5 }; // Another reference type
number1 === number2; // False, because although number1 and number2 hold the same values, they are still distinct objects.

See Salman's answer for a proper solution.

James
  • 119
  • 4
  • "*The mismatched times will cause the === comparison to fail.*" No they wont. `===` fails because it's comparing Date objects as objects, and two different objects are never `===` to each other per ECMA-262. The difference with comparison operators like `<` is that they coerce the values to number first, so they compare the time value, not the objects themselves. – RobG Feb 23 '19 at 00:43