0

I have code that gets data from the Application State and then show data inside component.html.

component.ts

myData$: Observable<IMyData>;

ngOnInit() {
   this.myData$ = this.myStore.select(fetchMyData);

   // here I get a code and I use it to dispatch a new action
   this.myStore.select(codeSelector).pipe(
      map((code) => this.myStore.dispatch(myDataAction({ code: code })))
    ).subscribe();
}

component.html

{{myData$.myField}}

The code above works perfectly.

Now, instead of calling the subscribe() method inside component.ts, I'd like to use async pipe inside component.html, this way:

<ng-container *ngIf="myData$ | async as data">
{{data.myField}}
   

When I do this nothing is shown inside component.html. I understood that inside my latter code I have problems with the operators I used.

I used the async pipe many times, but only when dispatching standard actions; I never used it when the action was dispatched inside an operator.

Can you helping me understanding my error?

Matt
  • 265
  • 4
  • 17
  • Inside map operator you are returning action instead of obserable map((code) => this.myStore.dispatch(myDataAction({ code: code }))) – Chellappan வ Jun 05 '21 at 05:27
  • Hi @Chellappanவ, how should I edit my code? – Matt Jun 05 '21 at 10:59
  • 1
    Your `subscribe()` is subscribing to `this.myStore.select(codeSelector)`. Without it, your store selector won't return anything since it is a cold observable. And in return, it won't run your action, and possibly won't update your store data that `fetchMyData` is selecting. Btw, as one answer suggests, you should use `tap()` instead of `map()` – Frank Fajardo Jun 05 '21 at 12:32
  • 1
    Hi @FrankFajardo, thank you for the explanation. Now I get that I have to subscribe to "this.myStore.select(codeSelector)" in order to make "this.myData$ = this.myStore.select(fetchMyData)" works; then I can use async pipe on "myData$" inside the template. – Matt Jun 05 '21 at 13:35

1 Answers1

1

Try tap operator for side effects intead of map

   data$ = this.myStore.select(codeSelector).pipe(
      tap((code) => this.myStore.dispatch(myDataAction({ code: code })))
    )

Then inside component

<ng-container *ngIf="myData$ | async as data">
</ng-container>
Chellappan வ
  • 23,645
  • 3
  • 29
  • 60
  • hi @Chellapan, probably I didn't explain well. If I use subscribe(), as you suggested, my code works. What I was trying to do is to avoid using .subscribe() and use async pipe (that automatically subscribe and unsubscribe) inside the template – Matt Jun 05 '21 at 11:49
  • 1
    acutally when using async pipe you dont need to subscribe inside component inside you can use tap operator. it will get invoked when async pipe resolved – Chellappan வ Jun 05 '21 at 12:57
  • Thank for you help man. Actually the code you wrote is exactly the code I wrote before looking for help here on stackOverflow. There was just on little difference: I can't do "data$ = this.myStore.select..." because "data$" has a type (as you can see in my post is "IMyData" type), and "this.myStore.select..." return just a string (that I just pass to the action). Anyway I think FrankFajardo hit the spot: I have to subscribe() to "this.myStore.select(codeSelector)" to make the whole code working. – Matt Jun 05 '21 at 13:51
  • 1
    @Matt yes you need to subscribe inorder to get the flow works. – Chellappan வ Jun 06 '21 at 04:42