Reputation: 29
this is my first Stack Overflow post so bare with me if I formatted anything incorrectly.
This is my first Angular project and I can't assign data retrieved from the http.get().subscribe(...) method to my component class variable.
My component:
...
export class LeafletMapComponent implements OnInit, AfterViewInit {
data
constructor(private ps: PeopleService, private NgZone: NgZone) {}
ngAfterViewInit(): void {
console.log(this.allData) **DOESN'T WORK (logs undefined)**
}
ngOnInit(): void {
this.ps.httpGetData().subscribe( data => {
this.data= data
console.log(this.data) ***WORKS (logs all my data) BUT...***
})
console.log(this.data) ***THIS DOESN'T WORK... WHY? (logs undefined)***
}
}
My Service:
...
@Injectable({
providedIn: 'root'
})
export class PeopleService implements OnInit {
...
httpGetData() {
return this.http.get<any>(this.URL) **WORKS**
}
...
}
My question is: In this piece of code
ngOnInit(): void {
this.ps.httpGetData().subscribe( data => {
this.data= data
console.log(this.data) ***WORKS (logs all my data) BUT...***
})
console.log(this.data) ***THIS DOESN'T WORK... WHY? (logs undefined)***
}
Because I have already assigned my data to a class variable (this.data = data) inside the
.subscribe( data => {this.data = data})
method, I assume that I would be able to console.log(this.data) right after the subscribe method inside the ngOnInit() function, I would assume that this.data has already been initialized and can be accessed anywhere
I want to retrieve data as soon as my component loads, assign it to my class variable so my variable can be used in the ngAfterViewInit() function. However, inside the .subscribe() method, I am able to assign the returned data to my class variable "this.data" and log it, but, console.log(this.data) only works inside the .subscribe() method, nowhere else.
Also, does NgAfterViewInit() run before or after ngOnInit()? I am trying to access my class variable (this.data) from the NgAfterInit() function, but I must get the data from my service before I can do that...
Does this have to do with modifying Observable objects?
Edit: console.log(this.data) now works inside the ngOnInit function when I changed to a async function
async ngOnInit(): Promise<void>{
const res = await this.ps.httpGetData().toPromise()
this.data = res
}
But ngAfterViewInit won't detect the change because it is still logging undefined for the value this.data.
Please help and thanks in advance!
Upvotes: 0
Views: 570
Reputation: 718
Based on the code you've written, this is probably the sequence of events:
ngOnInit
in LeafletMapComponent
is called
console.log(this.data)
which prints undefined
ngAfterViewInit
is called
console.log(this.data)
which again prints undefined
subscribe
callback is called
this.data
is setundefined
valueThe solution to this is to make sure that the HTTP request finishes in ngOnInit
. You can achieve this like so:
async ngOnInit(): Promise<void> {
this.data = await this.ps.httpGetData().toPromise();
console.log(this.data)
}
ngAfterViewInit()
will get called after ngOnInit()
is called according to the Angular documentation about lifecycle hooks. However, if ngOnInit()
is an async function, then it may complete after ngAfterViewInit()
because Angular will not await the Promise returned by ngOnInit()
. This means that you have to store a Promise
or an Observable
as your class variable instead of just the raw data in order to keep track of the fact that its an async value.
Upvotes: -1
Reputation: 199
Your code assigns the data correctly, however, it seems like you aren't clear on the concept of asynchronous code.
When you call subscribe
on your observable, that's an asynchronous call, meaning your code continues execution without waiting for the execution of the observable to complete. In other words, the code sends a request and continues execution without waiting for the response. Once the response is available, the callback function you supply to the subscribe
method as an argument is executed. That's why the console.log()
you call after subscribe
logs nothing.
As for your question about ngAfterViewInit
, it executes after ngOnInit
.
Read more about this in Angular Docs
Upvotes: 0