twiz
twiz

Reputation: 10558

Angular2 ngrx/store with route parameters

I'm updating an app to use ngrx/store, but I can't figure out how to make it work with route parameters.

Currently, I am just using ActivatedRoute and using this.route.params inside the ngOnInit() of my components. So something like this:

ngOnInit(): void {
   this.route.params
      .switchMap((params: Params) => {
        return this.item_service.get(params['item_id'])
      })
      .subscribe((item) => {
        this.item = item;
      });
}

Now that I'm using ngrx/store, I need to use an observable for the store. Basically I am trying to accomplish something like this:

this.item = this.store.select('item').filter((item: Item) => {
    return item.id == magically_obtained_params['item_id'];
});

Is there a way to make this work?


Update (2016/12/06):

I added an answer to expand on FunStuff's answer, since it didn't fully provide what I want. I haven't accepted either answer, as I think there is likely a better way to deal with this.

To clarify my question, I am trying to make this work in a way that this.item is an Observable.

Upvotes: 0

Views: 1496

Answers (2)

twiz
twiz

Reputation: 10558

I got pointed in the right direction thanks to FunStuff's answer, but it didn't fully answer how to use combineLatest() in relation to an Angular2 component.

Here is the solution I came up with that allows you to set an Observable property on the component:

ngOnInit(): void {
    this.item = Observable.combineLatest(
        this.store.select('item'),
        this.route.params
    ).switchMap(function(items, params) {
        return items.filter((item) => {
            return item.id == params['item_id'];
        })
    });
}

This works, but for my case I decided to go a step further. Instead of using combineLatest(), I moved the filter logic in the switchMap() into my service instead.

With this implemented, my component then looked like:

ngOnInit(): void {
    this.route.params.subscribe((params: Params) => {
        this.item = this.item_service.getItem(params['item_id']);
    });
}

And on my service I have a method like this:

getItem(item_id: string): Observable<{}> {
    return this.store.select('item').switchMap((items: any) => {
        return items.filter((item: any) => {
            return item.id == item_id;
        });
    });
}

I think I like this better since the component doesn't need to know about the Store at all, and it avoids needing to combine Observables.

Upvotes: 0

Bazinga
Bazinga

Reputation: 11194

You can use Rx combinelatest.

Merges the specified observable sequences into one observable sequence by using the selector function whenever any of the observable sequences produces an element.

this.item = Rx.Observable.combineLatest(
    this.store.select('item'),
    this.route.params
);

this.item.subscribe([item, params] => {
   return item.id == params['item_id'];
});

Upvotes: 3

Related Questions