Search code examples
angularreduxngrxngrx-router-store

NgRx - Multi level route params not able to access from CustomSerializer Router Store


I have a path declared like:

{
  path: 'app/:userId',
  children: [...AppChildrenRoutes]
}

And then, inside AppChildrenRoutes

{ path: 'feature', component: MainFeatureComponent }

So, at some point of my application I can have localhost:4200/app/123/feature. Inside this component, with some action, I can navigate to another route like this:

this.router.navigate([
  'app',
  this.userId,
  'feature',
  { search: this.searchFor }
]);


Consider it as a big enterprise sized application that is changing architecture, to use NgRx, step by step.
So, I faced a problem with Router Store. I've set up everything and it works.
Following Router Store docs I wrote a Custom Serializer and it looks like this

serialize(routerState: RouterStateSnapshot): RouterStateUrl {
  const { url } = routerState;
  const queryParams = routerState.root.queryParams;

  while (route.firstChild) {
    route = route.firstChild;
  }
  const params = route.params;

  return { url, queryParams, params };
}

And I found out that, considering a URI like

localhost:4200/app/123/feature;search=blue

the route.params returns only the search param, not both userId and search.

- How can I implement a CustomSerializer that returns all params from the path? (in this case, both userId and search).

I kinda tried but failed to, each iteration of the while loop, check if there was a param and add them to a object until the last one. Good, Ok or Bad approach? How could I work that and not fail?
Thanks.


Solution

  • I had a similar problem and solved it by extending the params object every time I go through the loop.

    My CustomSerializer now looks like this:

    export class CustomSerializer implements RouterStateSerializer<RouterStateUrl> {
    serialize(routerState: RouterStateSnapshot): RouterStateUrl {
        let route = routerState.root;
    
        let params = {};
        while (route.firstChild) {
            params = {
                ...params,
                ...route.params
            };
            route = route.firstChild;
        }
    
        const {
            url,
            root: { queryParams }
        } = routerState;
    
        return { url, params, queryParams };
    }
    

    }