blue piranha
blue piranha

Reputation: 3874

Unable to load data inside ngOnInit

My goal is to load a dropdown when a component renders. I have a service which hits a url and gets json data. Something like this

 @Injectable()
 export class StudentListService {

 constructor(private http: HttpClient) {}

 studentListUrl: string ="http://www.somecollege.com/students";

 public getStudentList() {
    return this.http.get(this.studentListUrl);
}

I have a component (StudentListComponent) which would display student names that I get from the service, in a dropdown.

 export class StudentListComponent implements OnInit {
    items: any = [];

    constructor(private studentListService: StudentListService){}

    ngOnInit() {
       this.items = this.studentListService.getStudent().subscribe(
           data => {this.items = data},
           err => console.error(err),
           () => console.log('Done Loading Student Data'));

       //////////  Here this.items is undefined 

    }

However if I put a button on StudentListComponent html and use its click event to display this.items, I see the data

 buttonClicked() {
  console.log(this.items); /// see the students in console)
 }

Why is this.items undefined in ngOnInit() and how can I get the data to populate when the component renders?

Upvotes: 0

Views: 1216

Answers (4)

Sandy Sanap
Sandy Sanap

Reputation: 753

ngOnInit() {
       setTimeout(()=>
          {
            this.studentListService.getStudent().subscribe(response =>{
             this.items = response;
          },error=>{
           console.log(error);
         });
     },1000);
 }

Upvotes: 1

SiddAjmera
SiddAjmera

Reputation: 39432

As Amit mentioned, since this is an async call, your data won't be available untill the subscribe block runs. So you won't be having access to data outisde it

Read the comments in the below code to understand:

export class StudentListComponent implements OnInit {
  items: any = [];

  constructor(private studentListService: StudentListService) {}

  ngOnInit() {
    this.studentListService.getStudent().subscribe(
      data => {
        this.items = data;
        //////////  Here this.items WILL BE DEFINED
      },
      err => console.error(err),
      () => console.log('Done Loading Student Data'));

    //////////  Here this.items WILL BE undefined as this will run synchronously i.e. it won't wait for this.studentListService.getStudent() to run.

  }

}

Upvotes: 4

Amit Chigadani
Amit Chigadani

Reputation: 29705

Remove this assignment this.items = this.studentListService.getStudent().... You are trying to assign Subscription object to this.items.

ngOnInit() {
       this.studentListService.getStudent().subscribe(
           data => {this.items = data},
           err => console.error(err),
           () => console.log('Done Loading Student Data'));

}

Note : You can only access it once the http (asynchronous) call is completed. And when it is completed, your dropdown should automatically load those items. If you try to print it outside subscribe block, it gives you undefined.

Upvotes: 0

Harun Yilmaz
Harun Yilmaz

Reputation: 8558

The getStudentList method of the service returns an Observable therefore it is an async function. So data => {this.items = data} line performs only after the subscription is completed. But this.items is not undefined since you assign it an empty array with items: any = [], it is only empty.

You can log the values with buttonClicked method because your http request has been completed.

I think you need to get more familiar with Observable from RxJS.

Here is the official docs of HttpClient: https://angular.io/guide/http

Upvotes: 0

Related Questions