Reputation: 71
Dears,
I am stuck, i have followed simple angular.io tutorial for http.get and observables, but i am not able to render the data in the view.
My service:
import { Injectable } from "@angular/core";
import { HttpClient } from "@angular/common/http";
import { Observable } from "rxjs";
import { map } from "rxjs/operators";
const baseUrl = "http://localhost:4000";
const fetchAllHeroesUrl = "/heroes";
@Injectable({
providedIn: "root",
})
export class HeroesService {
constructor(private http: HttpClient) {}
getHeroes(): Observable<any> {
return this.http.get(baseUrl + fetchAllHeroesUrl);
}
}
My component:
import { Component, OnInit } from "@angular/core";
import { HeroesService } from "./../shared/services/heroes.service";
import { Observable } from "rxjs";
@Component({
selector: "app-hero-list",
templateUrl: "./hero-list.component.html",
styleUrls: ["./hero-list.component.scss"],
})
export class HeroListComponent implements OnInit {
public listOfHeroes$: any;
constructor(private heroesService: HeroesService) {}
ngOnInit() {
this.getAllHeroes();
}
getAllHeroes(): void {
this.heroesService
.getHeroes().subscribe((value: any) => this.listOfHeroes$ = value.data);
}
}
my template:
<mat-list>
<mat-list-item *ngFor="let hero of listOfHeroes$ | async">
<img
matListAvatar
src="hero.avatar_url"
alt="hero.full_name">
<h3 matLine>{{hero.full_name}}</h3>
<p matLine>
<span>{{hero.description}}</span>
<span class="demo-2">-- {{hero.type}}</span>
</p>
</mat-list-item>
</mat-list>
but still nothing is showing in the view (in webbrowser, also i have checked Network tab in dev tools, and the data come from my local erver), whenever i console.log(this.listOfHeroes$) i get undefined Shouldn't this be working? am i missing something?
Upvotes: 0
Views: 4633
Reputation: 31105
You are both subscribing in the controller and using the async
pipe. It should be either of the two. Both has it's advantages and disadvantages. In this scenario, I'd recommend you to do the following
Remove getAllHeroes()
function altogether and modify the controller
export class HeroListComponent implements OnInit {
public listOfHeroes$: any;
constructor(private heroesService: HeroesService) {}
ngOnInit() {
this.listOfHeroes$ = this.heroesService.getHeroes();
}
}
And in the template
<ng-container *ngIf="listOfHeroes$ | async as list">
<mat-list-item *ngFor="let hero of list?.data">
<img
matListAvatar
src="hero.avatar_url"
alt="hero.full_name">
<h3 matLine>{{hero.full_name}}</h3>
<p matLine>
<span>{{hero.description}}</span>
<span class="demo-2">-- {{hero.type}}</span>
</p>
</mat-list-item>
<ng-container>
One reason why I prefer async
here is because it takes care of the unsubscribing from the HTTP GET to avoid potential memory leak issues.
Upvotes: 2
Reputation: 11934
The async
pipe needs to be given a promise or an observable.
You could do this:
this.listOfHeroes$ = this.heroesService.getHeroes();
as you can see, there is no need to subscribe in your component. the async
pipe will handle the subscription & unsubscription for you.
Upvotes: 1