Search code examples
javascriptangularclassconstructorngoninit

Why am I unable to get access to object that was set on ngOnInit


Ran into a few problems lately and wonder why I can't access an object, that was set in the ngOnInit function for later purposes, like in another function?

I want to access and use this.appointmentDetailId in my cancelAppointment() function but it is undefined. Hope someone can help. Thanks.

Here's my code:

export class AppointmentDetailComponent implements OnInit {
  id: any;
  appointmentDetailId: any;
  appointmentDetail$: Observable<AppointmentDetails>;
  appointmentDetail: AppointmentDetails;
  pageTitle = 'Some Default Title Maybe';

  constructor(
    private route: ActivatedRoute,
    private title: Title,
    private apiService: APIService
  ) {
    this.appointmentDetailId = this.id;
    console.log(this.appointmentDetailId);
  }

  ngOnInit() {
    this.route.paramMap
      .pipe(
        tap((params: ParamMap) => {
          this.id = params.get('id');
          // Or this.id = +params.get('id'); to coerce to type number maybe
          this.pageTitle = 'Termin Details: ' + this.id;
          this.title.setTitle(this.pageTitle);
        }),
        switchMap(() => this.apiService.getAppointmentDetailsById(this.id))
      )
      .subscribe((data: AppointmentDetails) => {
        this.appointmentDetail = data;
        console.log(this.appointmentDetail);
      });
  }

  cancelAppointment() {
    console.log(this.appointmentDetailId);
    this.apiService.cancelUserAppointment(this.appointmentDetailId);
  }
}

Solution

  • In the constructor you set this.appointmentDetailId = this.id which sets the value to the initial value of this.id (probably undefined);

    Later you set this.id = params.get('id'), but this will not change this.appointmentDetailId, because they're two different objects.


    If you want this.appointmentDetailId to always match this.id you should make it a simple wrapper, rather than its own object.

    export class AppointmentDetailComponent implements OnInit {
      id: any;
      get appointmentDetailId() {
        return this.id;
      }
      set appointmentDetailId(value: any) {
        this.id = value;
      }
    
      // Other code
    }
    

    Using a custom get and set method, you can still access this.appointmentDetailId as if it were it's own field - but it will actually be the same as this.id. Now, any changes to either field will always be in sync.

    // Always true
    this.appointmentDetailId === this.id
    
    this.appointmentDetailId = 123;
    this.appointmentDetailId === 123; // True
    this.id === 123; // True;
    
    this.id = "Test";
    this.appointmentDetailId === "Test"; // True
    this.id === "Test"; // True
    

    Alternatively, if you can simply omit the set method and then you'll just be able to access the same value, but you cannot change it.

    // Always true
    this.appointmentDetailId === this.id
    
    this.appointmentDetailId = 123; // Error
    
    this.id = "Test";
    this.appointmentDetailId === "Test"; // True
    this.id === "Test"; // True