Jay Marz
Jay Marz

Reputation: 1912

Undefined global variable but showing in view of Angular 2

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.

Upvotes: 1

Views: 606

Answers (2)

G&#252;nter Z&#246;chbauer
G&#252;nter Z&#246;chbauer

Reputation: 657466

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();
     }
}

Upvotes: 1

Vivek Doshi
Vivek Doshi

Reputation: 58573

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);
}

Upvotes: 1

Related Questions