angularparametersquery-stringangular-routingangular-router

merge two ParamMap angular


I have the following code that works fine:

let urlParameters = combineLatest(
  [this.route.params, this.route.queryParams], (params, queryParams) => ({
      ...params, ...queryParams
}));

urlParameters.subscribe(params => {
  console.log(params["type"]);
});

in the result I have new object and can access as params["type"]

but can I do the same with queryParamMap and paramMap? like:

let urlParameters = combineLatest(
  [this.route.paramMap, this.route.queryParamMap], (params, queryParams) => ([
    ...params, ...queryParams
]));

urlParameters.subscribe(params => {
  console.log(params.get("type"));
});

and I can use ParamMap methods like params.get("type")


Solution

  • First access the keys using paramMap.keys, then loop these values and store them in a temporary object finalParams (do this for all map value you want to merge, here it is paramMap and queryParamMap), then we can use convertToParamMap from @angular/router to convert it to param map, with both the merged values.

    The paramMap is a custom class ParamMap - Source Code and not the default Javascript map, hence, we need to recreate it with the respective properties to merge them.

    import { Component } from '@angular/core';
    import { ParamMap } from '@angular/router';
    import { convertToParamMap } from '@angular/router';
    import { ActivatedRoute } from '@angular/router';
    import { combineLatest } from 'rxjs';
    import { map } from 'rxjs/operators';
    
    @Component({
      selector: 'ngc-child',
      template: 'Child:<p>Param: {{params.id}}</p>',
    })
    export class ChildComponent {
      params: any;
    
      constructor(route: ActivatedRoute) {
        let urlParameters = combineLatest([
          route.paramMap,
          route.queryParamMap,
        ]).pipe(
          map(([paramMap, queryParamMap]) => {
            const finalParams = {};
            this.mapParams(paramMap, finalParams);
            this.mapParams(queryParamMap, finalParams);
            return convertToParamMap(finalParams);
          })
        );
    
        urlParameters.subscribe((result) => {
          console.log(result.get('id'));
          console.log(result.get('test'));
        });
      }
    
      mapParams(paramMap, finalParams) {
        const keys = paramMap.keys;
        keys.forEach((key: string) => {
          const allParams = paramMap.getAll(key);
          finalParams[key] = allParams?.length <= 1 ? paramMap.get(key) : allParams;
        });
      }
    }
    

    Stackblitz Demo