Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get unique/latest value from observable in component class (result of store selector)

Tags:

angular

ngrx

My application is using Angular and ngrx store. I am using a selector in the store to get the username property of the app state in my component constructor:

test-component.ts

export class TestComponent {
    username$: Observable<string>;
    constructor(private store: Store<fromRoot.AppState>) {
        this.username$ = this.store.select(fromRegistration.getUsername);
    }

    testMethod() {
         //I need the value of the username observable here as a string
    }

}

This is working fine. I need to print the username in the component's template, which I am doing by using the async pipe:

test-component.html

<div>
{{username | async}}
</div>

This is also working correctly.

Now, I need to call a service from a method in TestComponent that sends the username as an argument. How can I achieve this? Do I need to stop using the async pipe and subscribe to the selector to then assign the username property (which would then be declared as a string) to the value of the observable?

To note: the username observable will only have 1 value, once I get 1 value I can stop watching it.

I understand by using the async pipe the component unsubscribe from the username observable automatically, when does this happen and how does the component knows I don't need to watch it anymore?

If I can't use the async pipe, how and when do I unsubscribe?

like image 360
MartaGalve Avatar asked Feb 20 '18 04:02

MartaGalve


1 Answers

I usually go with Maciej Treder's First thought as I try to use dumb components whenever possible, but in some cases when I need the new value from a selector to perform extra stuff inside my component that I'm going to async pipe it to my template anyway (so I don't need any subscribing), I simply use rxjs tap operator which is the pipeable operator name of do. So I replace this:

ngOnInit() {
  this.selected$ = this.store.pipe(select(fromItems.getSelectedBrand));
}

By this:

import { Store, select } from '@ngrx/store';
import { tap } from 'rxjs/operators';

...

ngOnInit() {
  this.selected$ = this.store.pipe(
    select(fromItems.getSelectedBrand),
    tap((brand: Brand) => {
      /**
       * do logic here
       */
    })
  );
}

Now if for some reasons you do need to subscribe to it without async piping it to any template as done in Maciej Treder's second solution, I'd suggest using ngOnDestroy to unsubscribe from it. You'll find more about it here:

  • How to unsubscribe from ngrx/store?
  • When to Unsubscribe in Angular - by Netanel Basal
like image 185
Salem Ouerdani Avatar answered Oct 13 '22 01:10

Salem Ouerdani