1

I have a service method which gets dummy data and returns an observable.

private dummySubject = new BehaviorSubject<Dummy>(null);
dummy$ = this.dummySubject.asObservable();

loadDummyData(id: string): Observable<Dummy> {
  const BASE_URL = 'someurl/' + id; 
  return this.http.get<Dummy>(BASE_URL).pipe( 
    tap((dummyData: Dummy ) => {
      console.log('In Service ', dummyData); //LOGS DATA HERE
      this.dummySubject.next(dummyData);
    })
  );
}

In another service, I use the switchMap operator to map a user id into my loadDummyData method.

anotherService

loadDummyData(){
  this.dummyService.user$.pipe(
    switchMap((user: User) => {
      return this.dummyService.loadDummyData(user.id);
    })
  ).subscribe();
}

Then in my getData component

localData: Dummy;
dummy$: Observable<Dummy> = this.dummyService.dummy$;

ngOnInit() {
  1) this.anotherService.loadDummyData(); //Causes data to be loogged in service
  2) this.dummyService.loadDummyData('12345').subscribe( //causes data logged in service
    (dummy: Dummy) => {
      this.localProfile = dummy;
      console.log(this.localProfile, 'data in component'); //local data log
    }, 
    err => {
      console.error(err);
    }
  );
  console.log(this.localProfile, 'In ngOnint'); //undfiened 
}

In the getData component, I make 2 calls to the dummyService method,

  1. call anotherService => loadDummyData() (which uses switch map to load data)
  2. Call dummyService => loadDummyData() directly passing an Id and subscribing.

both times the data is logged in the console and seems to be coming back. However, in my template, the async | is not displaying the data. The loadProfile variable is also getting undefined in the second call to get the data.

Template

<div *ngIf="dummy$ | async as dummyData">
  <span class="pull-right" *ngIf="dummyData.canViewAdmin">
    <a (click)="openChangeUserModal()">Change user</a>
  </span>
  <p>{{dummyData.name}}</p>
</div>

What am I missing here?

DevRight
  • 345
  • 1
  • 6
  • 25

2 Answers2

0

You are not assigning dummyData anywhere!

Change to this:

loadDummyData(): Observable<Dummy> {
  return this.dummyService.user$.pipe(
    switchMap((user: User) => this.dummyService.loadDummyData(user.id)),
  );
}

and

dummy$: Observable<Dummy> = this.dummyService.dummy$;

ngOnInit() {
  this.dummy$ = this.anotherService.loadDummyData();
MoxxiManagarm
  • 8,735
  • 3
  • 14
  • 43
0

Since you haven't put up your complete code, the issue that's evident over here is that dummy$ is not assigned the expected value in dummyService. You'll have to assign value in dummy$ likethis.dummy$ = this.dummySubject.asObservable(); then only you can use its value in component.

And where is load loadUserProfile method.

In your case if you remove async pipe and bind your html with localProfile, then too it would work.

Change your html

 <div *ngIf="localProfile">
  <span class="pull-right" *ngIf="localProfile.canViewAdmin">
    <a (click)="openChangeUserModal()">Change user</a>
  </span>
  <p>{{localProfile.name}}</p>
</div>

Outside the subscribe callback, localProfile will be undefined because its async call.

Anand Bhushan
  • 765
  • 8
  • 18
  • I have updated the question, the localProfile var is returning undefined when we try to call it outside the subscribe body. And causes a template error if add to the template. – DevRight Dec 04 '19 at 13:12
  • I did the exact as above the localProfile causes a template issue, looks like the localProfile var does not get populated outside the subscribe body. – DevRight Dec 04 '19 at 13:41
  • how come your console.log is working inside the subscription then? – Anand Bhushan Dec 04 '19 at 13:43
  • That's a great question. I logged it outside the subscribe body and it is undefined, I think it is to do with the call to service been an async call and console being a synchronise. – DevRight Dec 04 '19 at 13:47