Reputation: 49804
When I use ngrx, if I want to transfer a value to its child component, I am doing like this:
// parent component
<product1-component [product]="(model$ | async)?.product1"></product1-component>
<product2-component [product]="(model$ | async)?.product2"></product2-component>
this.model$ = Observable
.combineLatest(
this._store.select('products')
)
.let(ProductsModel());
Right now I want to use the value product1
and product2
inside of the parent component itself. I am doing like this right now (is there any better way?):
this.model$.subscribe((model: any) => {
if (!model) return;
// Right now here no matter which value changes, it will run.
// However what I want is:
// if `product1` changes, do something
// if `product2` changes, do something
});
How can I know which state value changes? Thanks
Upvotes: 0
Views: 2906
Reputation: 335
The select
function of the store returns an Observable
.
As such, you are then free to use any of the operators available in Rxjs to achieve what you want.
To answer your question what you can do is :
const nonNullModel$ = this.model$.filter(x => !!x);
this.product1$ = nonNullModel$.map(x => x.product1);
this.product2$ = nonNullModel$.map(x => x.product2);
Keep in mind that every time your products
state slice changes, both product1$
and product2$
will push a new value.
If you are only interested when the product1 or product2 really changes, you can use the distinctUntilChanged
operator:
this.product1$ = nonNullModel$.map(x => x.product1).distinctUntilChanged();
Because this is pretty much what select
does for you, you could instead write:
this.product1$ = this_store.select(x => x.products && x.products.product1);
this.product2$ = this_store.select(x => x.products && x.products.product2);
You can now use each stream directly in your template using the async
pipe the same way you pass the value down to the child component.
<product1-component [product]="product1$ | async"></product1-component>
<product2-component [product]="product2$ | async"></product2-component>
JSON representation of my product 1: {{product1$ | async | json}}
If you want to do something in the parent component class:
this.sub1 = this.product1$.subcribe(p => // Do something with product 1);
this.sub2 = this.product2$.subcribe(p => // Do something with product 2);
Note that when you subscribe explicitly (as opposed to using async
pipe) to an observable, you should take care of unsubscribing when you component gets destroyed.
ngOnDestroy() {
this.sub1 && this.sub1.unsubcribe();
this.sub2 && this.sub2.unsubcribe();
}
Upvotes: 2