0
votes

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

enter image description here

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

enter image description here

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"?

3
Mind sharing relevant code of ProfiloServiceSatpal
Show the servicecallback
@Satpal added the serviceKasper Juner
In the subscribe can you do console.log(data) and please update your question with console data or image of consoleSivakumar Tadisetti
@SivakumarTadisetti added the console.log, anyway if in the service i set BehaviorSubject to new BehaviorSubject<any>(new Profilo); and i will do a *ngIf="profilo.id" instead of *ngIf="profilo" it will works, but i would a cleaner solution where i have profilo undefined and *ngIf="profilo"Kasper Juner

3 Answers

1
votes

In html use ? operator

<div *ngIf="profilo?.moduli?.ticketing" ></div>
1
votes

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.

0
votes

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>