angularroutesrouterangular-resolvernavigateurl

How to handle stored query params in angular route using resolvers to avoid any extra navigation?


I have this scenario: I am saving the query params in a service in order to keep alive this data if the user close the browser, using the resolvers I am using the result from the active route to add the missing parameters in the Init hook of the component, in some components this query parameters are involved to perform ui or service actions.

Resolver:

export const queryParamsResolver = (route: ActivatedRouteSnapshot) => {
  const productId = route.paramMap.get('id');

  if (!productId) {
    return of(undefined);
  }

  // is possible navigate from here instead of send the data the component and navigate from the componen
  return inject(CodeService).getQueryParamerts(+productId);
};

Navigate:

ngOnInit() {
    this.activatedRoute.data.subscribe(({ query }) => {
      // extra navigation is not required only provide query params to the current url
      this.router.navigate([], { queryParams: query });
    });
  }

Is possible to use a better implementation to handling stored query params for certain component. I wonder if is possible to assign this paramerts before any route resolution to help to avoid extra call, other components are depending of this query to reflect other behaviors in the ui and call services that are not requiered in the resolvers.

Live sample in stackblitz without the entire complexity.

enter link description here


Solution

  • You can navigate using the below code, I have put a check to avoid an infinite loop since navigating calls the resolver, which navigates again and so on, so this check will ensure that navigation stops when all query params are present. I hope it solves your issue

    import { inject } from '@angular/core';
    import {
      ActivatedRouteSnapshot,
      Router,
      RouterStateSnapshot,
    } from '@angular/router';
    import { of } from 'rxjs';
    import { switchMap, tap } from 'rxjs/operators';
    import { CodeService } from '../services/code.service';
    
    export const queryParamsResolver = (
      route: ActivatedRouteSnapshot,
      state: RouterStateSnapshot
    ) => {
      const router = inject(Router);
      const productId = route.paramMap.get('id');
      const status = route.queryParamMap.get('status');
      const code = route.queryParamMap.get('code');
    
      if (!productId) {
        return of(undefined);
      }
    
      // is possible navigate from here instead of send the data the component
      return inject(CodeService)
        .getQueryParamerts(+productId)
        .pipe(
          switchMap((query: any) => {
            if (!status || !code) {
              return router.navigate([state.url], {
                queryParams: query,
                queryParamsHandling: 'merge',
              });
            }
            return of(true);
          })
        );
    };
    

    stackblitz