0

Why is currentdate in this.currentdate.getTime() coming back as undefined?

newlisting = this.formBuilder.group({
    availabledate: new FormGroup({
      xyz: new FormControl()
    },[this.mainservice.getcurrenttime.bind(this)])
})
@Injectable({providedIn: 'root'})
export class MainService {

  constructor(){}
 
  currentdate: Date = new Date();

  getcurrenttime(control: FormGroup){

    console.log(this.currentdate.getTime())  <~~ Generates Error!!!

    if(condition){
      return {date: true};
    }
    return null;
  }

}
New Developer
  • 61
  • 1
  • 8

2 Answers2

1

When you do something like this.mainservice.getcurrenttime.bind(this), it creates a bound function.

Due to the above created bound function, in your case within getcurrenttime() method this would be referred to as YourComponent instance.

Since the component doesn't have any property named currentdate declared, this.currentdate will result in undefined and trying to read getTime() on it will result in an error.


Below are few of the alternatives you can use:

  1. Bind it to the mainservice instance
this.mainservice.getcurrenttime.bind(this.mainservice)
  1. Return a ValidatorFn from getcurrenttime as below, so that you don't lose the this context. (I would recommend this approach)
// Within MainService
getcurrenttime(): ValidatorFn {
  return (control: AbstractControl) => {
    console.log(this.currentdate.getTime());
    // Your logic
    return null;
  }
}

// Within YourComponent
this.mainservice.getcurrenttime()
  1. Define getcurrenttime as an arrow function and then you don't need to use bind.
// Within MainService
getcurrenttime = (control: AbstractControl) => {
  console.log(this.currentdate.getTime());
  // Your logic
  return null;
}

// Within YourComponent
this.mainservice.getcurrenttime  // No need to use .bind(...)

Should I write methods as arrow functions in Angular class

Siddhant
  • 2,911
  • 2
  • 8
  • 14
  • First thank-you, and interesting stuff. In example 1 (which worked), how does this work, wouldn't changing `this` to `this.mainservice` instead send the entire mainservice over to the function? Even with it working, I am not understanding how bind actually works maybe. I will try the other two options later today and report back any questions. – New Developer Feb 13 '22 at 13:11
  • https://stackoverflow.com/q/2236747/9471852 this post consists of multiple answers, which you might find helpful in understanding how `bind` works. – Siddhant Feb 13 '22 at 17:44
0

set validate without .bind()

newlisting = this.formBuilder.group({
    availabledate: new FormGroup({
      XYZ: new FormControl()
    },[this.mainservice.getcurrenttime()])
})

I think you can define that currentDate variable inside the method.

 const currentdate: Date = new Date();

and I think you should return something like this.

getCurrentTime(): ValidatorFn {
    return (formGroup: FormGroup): ValidationErrors | null => {
      const currentDate: Date = new Date();

      const year = formGroup.get('year').value;
      const month = formGroup.get('month').value;
      const day = formGroup.get('day').value;

      const selectedDate = new Date(year, month, day, 0, 0, 0, 0);

      if (selectedDate === currentDate) {
        formGroup.setErrors({ any_error: true }); // on your form group
        return null;
      } else return null;
    };
  }
Abolfazl Almas
  • 165
  • 1
  • 7