1

I am confused with my codes in Angular 2. In my ts file I have:

    import { Test } from '../../../../models/test';
    import { TestService } from '../../../../services/test.service';
    import { Job} from '../../../../models/job';
    import { JobService } from '../../../../services/job.service';

    export class TestTakeMcComponent implements OnInit {
          company_name: string;
          test: Test;
          job: Job;

          constructor(
            private testService: TestService,
            private jobService: JobService
          ) { }
          ngOnInit() {
            this.getTest();
            this.getJob(this.test.id);
          }
          getTest(){
            this.testService.getById(40).subscribe(
              test => {
               if(test.data.data.length != 0){
                 this.test = test.data.data[0];
               }
              }
            );
          }
         getJob(id: number){
           this.jobService.getJobByTestId(id).subscribe();
         }
    }

And in my HTML file I have:

<h3 class="box-title">{{ test?.title }} </h3>

Surely, the data binding {{ test?.title }} is working and showing the data. But during the call of another function getJob(this.test.id) on my ts file, it says an undefined parameter. How this became undefined when it is showing perfectly in the view? I wanted to use the data inside this.test variable to other functions but I cannot since it is undefined. Please someone has the same issue with me and how did you fix this problem. Thank you.

Jay Marz
  • 1,861
  • 10
  • 34
  • 54

2 Answers2

1

This is because the console.log() is executed before this.test gets a value assigned. The execution is async, which means it scheduled to run later, while the execution of the sync code continues immediately.

{{ test?.title }} is undefined first but updated later, but the change happens too fast for a human too recognize.

If you move the console.log() you'll see the value

      getTest(){
        this.testService.getById(40).subscribe(
          test => {
           if(test.data.data.length != 0){
             this.test = test.data.data[0];
             console.log(this.test);
           }
          }
        );
      }

update

export class TestTakeMcComponent implements OnInit {
      company_name: string;
      test: Test;
      job: Job;

      constructor(
        private testService: TestService,
        private jobService: JobService
      ) { }
      ngOnInit() {
        this.getTest().subscribe(val => 
            this.getJob(this.test.id));
      }
      getTest(){
        // add `return` and replace `subscribe` by `map`
        return this.testService.getById(40).map(
          test => {
           if(test.data.data.length != 0){
             this.test = test.data.data[0];
           }
          }
        );
      }
     getJob(id: number){
       this.jobService.getJobByTestId(id).subscribe();
     }
}
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • but for example I will create another function using another service, `getJob(){ this.jobService.getJobByTestId(this.test.id).subscribe(); }` the call of this function will return an undefined parameter. That is my problem. It will not store the data globally in `this.test` variable. – Jay Marz Mar 30 '17 at 07:28
  • Hard to tell without seeing the code and how you use it. Perhaps the answers in http://stackoverflow.com/questions/36271899/what-is-the-correct-way-to-share-the-result-of-an-angular-2-http-network-call-in/36291681 give you some idea how to work with observables. There are also several tutorials out about how to use observables (with or without Angular) – Günter Zöchbauer Mar 30 '17 at 07:30
  • I updated my answer. You need to chain async calls, otherwise the order of execution will probably not be what you expect. – Günter Zöchbauer Mar 30 '17 at 07:37
1

Replace you code with this :

import { Test } from '../../../../models/test';
    import { TestService } from '../../../../services/test.service';

    export class TestTakeMcComponent implements OnInit {
          company_name: string;
          test: Test;

          constructor(
            private testService: TestService
          ) { }
          ngOnInit() {
            this.getTest();
            // console.log(this.test);
          }
          getTest(){
            this.testService.getById(40).subscribe(
              test => {
               if(test.data.data.length != 0){
                 this.test = test.data.data[0];
                 console.log(this.test);
                 this.getJob();
               }
              }
            );
          }

          getJob(){ 
              this.jobService.getJobByTestId(this.test.id).subscribe(); 
         }
    }

You have just put the console.log() at wrong place.

As this.testService.getById(40).subscribe is async part , so

ngOnInit() {
    this.getTest();
    // at this time we'll not have this.test ;
    // console.log(this.test);
}
Vivek Doshi
  • 56,649
  • 12
  • 110
  • 122
  • this also works like charm. but I have to select just 1 answer. But thanks anyway for another idea. – Jay Marz Mar 30 '17 at 07:45