5

This question is a duplicate of the following existing questions here on SO:

Angular router: how to replace param?

Generically replace Angular 2 route parameter and navigate

Angular 6 router - replace some of the parameters of the current route

Angular2-router: How to only change a parameter of a route?

How can I change a specific, internal route parameter in Angular2

None of the answers given to these questions fully solves the problem of replacing one segment in the url, therefore I am asking this question again.

Summarizing my situation:

These are some of the routes in my project (I did not come up with this myself, so please bear with me)

/:customer/static/part/of/url
/:customer/other/static/stuff
/something/for/the/:customer
/something/without/anything
/other/stuff/:customer/might/need

The Parameter ":customer" appears in various places of the url. My problem is that this customer-id might change in the backend without any action from the frontend. I am listening to changes on the backend and have to adjust the url accordingly in case the customer-id changes.

A simple string.replace won't do because technically the customer-id might actually and literally be "static" or "other".

Question:

How can I analyze the current url (ActivatedRoute?) to replace only the one part of the url concerning the customer-id (paramMap has "customer") while keeping the rest of the url as it is?

2
  • Did you found any solution? Commented Aug 13, 2019 at 7:45
  • sadly no........ Commented Aug 13, 2019 at 10:57

2 Answers 2

3

I did write own generator. Here is the code:

import { ActivatedRoute } from "@angular/router";

const defaultExtras: { 
  params: any, 
  preserveMatrix: boolean, 
  recursive: boolean, 
  preserveChildMatrix: boolean, 
  replaceChildParams: boolean 
} = {
  params: {},
  preserveMatrix: true,
  recursive: true,
  preserveChildMatrix: false,
  replaceChildParams: true
};

export function routerPathGenerator(
  route: ActivatedRoute, 
  extras?: { params?: any, preserveMatrix?: boolean, recursive?: boolean, preserveChildMatrix?: boolean, replaceChildParams?: boolean }
): any[] {
  const mergedExtras = { ...defaultExtras, ...extras };
  const path: any[] = [...replaceRouteParams(route.routeConfig.path.split('/'), { ...route.snapshot.params, ...mergedExtras.params })];

  if (mergedExtras.preserveMatrix) {
    path.push(replaceMatrixParams(route, mergedExtras.params));
  }

  if (mergedExtras.recursive && route.children.length > 0) {
    path.push(...routerPathGenerator(route.children[0], {
      params: mergedExtras.replaceChildParams ? mergedExtras.params : {},
      preserveMatrix: mergedExtras.preserveChildMatrix,
      recursive: mergedExtras.recursive,
      preserveChildMatrix: mergedExtras.preserveChildMatrix,
      replaceChildParams: mergedExtras.replaceChildParams
    }));
  }

  return path;
}


function replaceRouteParams(parts: string[], params: Object): any[] {
  return (parts || [])
    .map(part => (part.startsWith(':') && params.hasOwnProperty(part.substring(1)) ? params[part.substring(1)] : part));
}

function replaceMatrixParams(route: ActivatedRoute, params: Object): any {
  const matrix: any = {};
  Object.keys(route.snapshot.params)
    .forEach(key => 
      (route.routeConfig.path.split('/').some(p => p === ':' + key) ?
      '' : 
      matrix[key] = params.hasOwnProperty(key) ? params[key] : route.snapshot.params[key])
    )
  return matrix;
}

Suppose we have URL like this:

http://some.domain/warehouses/5;c=7;d=8/moves/42/items;a=1;b=2?e=77&f=88

where '/warehouses' points to lazy loaded module with routes:

const routes: Routes = [
  { path: '', component: WarehousesComponent },
  { path: ':id', redirectTo: ':id/stocks', pathMatch: 'full' },
  { path: ':id', component: WarehousesComponent, children: [
    { path: 'stocks', component: StocksComponent },
    { path: 'moves', component: MovesComponent, children: [
      { path: '', redirectTo: 'items', pathMatch: 'full' },
      { path: ':moveId/items', component: ItemsComponent },
      { path: 'initial', component: InitialComponent }
    ] }
  ] }
];

If I run the next code inside WarehousesComponent

    const commands = routerPathGenerator(this.route, {
      params: {
        id: 8,
        moveId: 24,
        c: 17,
        a: 666
      },
      preserveChildMatrix: true
    });

    this.router.navigate(commands, { queryParamsHandling: 'preserve', relativeTo: this.route.parent });

I'll navigate to

http://some.domain/warehouses/8;c=17;d=8/moves/24/items;a=666;b=2?e=77&f=88

I think it's your case just check extras params of routerPathGenerator

Sign up to request clarification or add additional context in comments.

Comments

1

To read a text pattern in a string, I would suggest a regular expression.

By example if your customer ID is like '123456' the regex can be /\d{6}/ (the slashes are here to describe the regex pattern, not the url ones) :

let url = '/something/for/the/123456' // 123456 denotes :customer here
let pattern = /\d{6}/;

let customerId = url.match(pattern);

Take care of defining a pattern that only matches the customer id in the URL.

You can find further informations on JavaScript regex here : https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/RegExp

And I almost forgot, you can replace a pattern in a string using the String.replace() function : https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/String/replace

3 Comments

Thanks for you answer! I am trying not to use String.replace though, because theoretically the customer-id might be anything, including "something"...
If you don't know what your :customer will look like neither its position in the url I wish you good luck :) don't you have other informations ?
@Abel, there is a router config which instructs angular router service how to resolve paths to components.And the main question is how to use the 'metadata' from this config for url segment substitution.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.