Reputation: 952
I'm trying to subscribe to a BehaviourSubject
that was set by parent component and get it in the child one, i'm trying to make the following in my component:
export class ModuliComponent implements OnInit {
public profilo: Profilo;
constructor(public profiloService: ProfiloService) { }
ngOnInit(): void {
this.profiloService.dataProfilo.subscribe(data => this.profilo = data); // setting profilo
}
}
But when i try to use profilo
in HTML i just get undefined
on asporto
or other *ngIf
What i'm doing wrong? should i initialize first the profilo
? if so even by setting onInit
or in constructor
the profilo = new Profilo();
i get the same error of undefined...
If i set a console.log to subscribe it return the right data, so asporto and other stuff from subscribe are not undefined.
As requested here is ProfiloService
@Injectable({
providedIn: 'root'
})
export class ProfiloService {
public dataProfilo = new BehaviorSubject<any>([]);
constructor(private http: HttpClient, private adapter: ProfiloAdapter) { }
profilo(idNegozio: string): Observable<Profilo>{
return this.http
.get(`${Globals.API_URL}/profilo/${idNegozio}`)
.pipe(map((data: any) => this.adapter.adapt(data)));
}
}
And here is the component where i'm setting the dataProfilo:
this.profiloService.dataProfilo.next(profilo);
Console.Log from subscribe data
EDIT:
If i add on parent div *ngIf="profilo.moduli"
it will works fine, but at this point if profilo is undefined why it is not enough to do a simple *ngIf="profilo"
?
Upvotes: 0
Views: 471
Reputation: 31135
If you're going to have an empty array by default and check if it's undefined in the template, I'd recommend you to use ReplaySubject
with buffer 1 instead. It's similar to BehaviorSubject
but doesn't need a default value.
@Injectable({
providedIn: 'root'
})
export class ProfiloService {
public dataProfilo = new ReplaySubject<any>(1);
constructor(private http: HttpClient, private adapter: ProfiloAdapter) { }
profilo(idNegozio: string): Observable<Profilo>{
return this.http
.get(`${Globals.API_URL}/profilo/${idNegozio}`)
.pipe(map((data: any) => this.adapter.adapt(data)));
}
}
Furthermore, if you were to subscribe to an observable in the controller only to use it directly in the template, you might as well use the async
pipe instead. At the least, it takes care of the unsubscription issue.
Child component
export class ModuliComponent implements OnInit {
public profilo$: Observable<any>;
constructor(public profiloService: ProfiloService) { }
ngOnInit(): void {
this.profilo$ = this.profiloService.dataProfilo;
}
}
Template
<ng-container *ngIf="(profilo$ | async) as profilo">
<section>
...
</section>
</ng-container>
The template within the <section>
tags doesn't have to be changed since we are using *ngIf
directive's as
signature to denote the current values from the observable.
Upvotes: 1
Reputation: 26
When init child component then the profilo var is undefine and the profilo var just have data when the API return data. Therefore, u can use "?" operator or check the profilo var as below.
<div *ngIf="profilo?.moduli?.ticketing" ></div>
OR
<div *ngIf="profile && profile.moduli && profile.profile.ticketing" ></div>
Upvotes: 0
Reputation: 2834
In html use ? operator
<div *ngIf="profilo?.moduli?.ticketing" ></div>
Upvotes: 2