0

I am working on the frontend of a Web app with Angular. I have an issue with the ngOnInit() method. This is my component.ts file:

export class TimesheetComponent implements OnInit {
  timesheetInfo: ITimesheetInfo;
  month: number;
  year: number;
  employeeEmail: string;
  dataSource: ITimesheetRow[] = [];

  constructor(private translate: TranslateService, private notify: NotificationService, private timesheetService: TimesheetService) {}

    getTimesheetInfo(employeeEmail: string, month: number, year: number): void {
      this.timesheetService.getTimesheetInfo(employeeEmail, month, year).subscribe({
        next: (data): void => {
          this.timesheetInfo = data;
          console.log(this.timesheetInfo);
        },
        error: (err): void => {
          if(err.status != 401) {
            this.notify.error(this.translate.instant('ERRORS.GENERAL_ERROR'))
          }
        }
      });
    }
    
    getRows(): void {
      this.timesheetService.getCurrentRows(this.timesheetInfo.id).subscribe({
        next: (data): void => {
            this.dataSource = data;
          },
        error: (err): void => {
          if (err.status != 401) {
            this.notify.error(this.translate.instant('ERRORS.GENERAL_ERROR'));
          }
        }
      });
    }

  ngOnInit(): void {

    this.employeeEmail = 'mymail@gmail.com';
    this.month = 1;
    this.year = 2021;

    this.getTimesheetInfo(this.employeeEmail, this.month, this.year);
    
    this.getRows();
  }

}

The variable timesheetInfo is displayed correctly with the new values (including the id) in the console, as asked inside the getTimesheetInfo() method. However, I still get this error:

ERROR TypeError: Cannot read property 'id' of undefined
    at TimesheetComponent.getRows (timesheet.component.ts:73)
    at TimesheetComponent.ngOnInit (timesheet.component.ts:340)

This is about the field this.timesheetInfo.id, which I use in the getRows() method: this method is used inside the ngOnInit() method. So it seems that the variable timesheetInfo isn't updated inside the ngOnInit() method. How is it possible?

lucia
  • 29
  • 5
  • you should chain your calls and make sure the second call is excecuted only when the first one is completed : take a look to this https://stackoverflow.com/questions/35268482/chaining-rxjs-observables-from-http-data-in-angular2-with-typescript – Benzara Tahar Jan 29 '21 at 11:13
  • edit your questions title, this problem has nothing to do with `ngOnInit()` – Farhad Jan 29 '21 at 11:37
  • @lucia please change the title of the question, this is not related to ngOnInit – Farhad Jan 29 '21 at 21:31

2 Answers2

0

by the time you are calling the getRows() the value of this.timesheetInfo is not set yet

you should either use async and await or call your getRows() method in the callback function of getTimesheetInfo()

    getTimesheetInfo(employeeEmail: string, month: number, year: number): void {
      this.timesheetService.getTimesheetInfo(employeeEmail, month, year).subscribe({
        next: (data): void => {
          this.timesheetInfo = data;
          console.log(this.timesheetInfo);

          // here, after you set this.timesheetInfo
          this.getRows();

        },
        error: (err): void => {
          if(err.status != 401) {
            this.notify.error(this.translate.instant('ERRORS.GENERAL_ERROR'))
          }
        }
      });
    }
Farhad
  • 494
  • 5
  • 20
  • I didn't want to confuse you with async/await but consider learning them cause they are the better and more readable way of doing this – Farhad Jan 29 '21 at 11:37
0

the recommended way of achieving this is by using the rxjs operators, you could do it like this.

    getTimesheetInfo(employeeEmail: string, month: number, year: number): void {
    this.timesheetService.getTimesheetInfo(employeeEmail, month, year)
      .pipe
      (
        tap(timeSheetInfo => {
          this.timesheetInfo = timeSheetInfo;
        }),
        switchMap(() => {
          return this.timesheetService.getCurrentRows(this.timesheetInfo.id);
        }),
        tap(data => {
          this.dataSource = data;
        }),
        catchError(err => {
          if (err.status != 401) {
            this.notify.error(this.translate.instant('ERRORS.GENERAL_ERROR'));
          }
          return EMPTY;
        })
      )
      .subscribe();
  }
waseemrakab
  • 315
  • 2
  • 9