Angular router: how to replace param?

家住魔仙堡 提交于 2019-12-20 10:41:57

问题


Let's suppose I've got 3 urls: /:projectId/info, /:projectId/users, /:projectId/users/:userId/profile. All of them have param projectId. UI has a component to switch from one project to another. So I need:

  1. Get current URL
  2. Change param by name (e.g. projectId)
  3. Navigate to new url

So I need something like this.router.replaceParam(currentUrl, {projectId: 'project_id_2'}) which will transform /project_id_1/users/user_id_1/profile into /project_id_2/users/user_id_1/profile (and any other URL with :projectId param)

I thought it's a simple and common problem but didn't find a solution in 1 hour. Suggested here solution doesn't work as noted in the last comment


回答1:


To navigate to particular link from current url, you can do something like this,

 constructor(private route: ActivatedRoute, private router: Router){}
 ngOnInit() {
     this.route.params.subscribe(params => {
         // PARAMS CHANGED ..    

         let id = params['projectid'];    
     });
 }
 navigate(){
     this.router.navigateByUrl(this.router.url.replace(id, newProjectId));
     // replace parameter of navigateByUrl function to your required url
 }

On ngOnInit function, we have subscribed to params so we can observe and executes our statements on any change in url parameter.




回答2:


You can use either HTML Or Ts

1 > In HTML

[routerLink]="['../info']"
        Or
[routerLink]="['../users']"
    like this etc....

2 > In Typescript

this.router.navigate(['../users'], { relativeTo: this.activatedRoute });



回答3:


Looking at your question , you want to change the 2 parameters .

As stated in :

https://angular.io/api/router/Router#navigatebyurl

You can implement router.navigate([yourprojectId, 'users', youruserId , 'profile'], {relativeTo: route});




回答4:


Would this help?

export class MyComponent {

  constructor(private router: Router, private route: ActivatedRoute){}

  public navigate(){
    const projectId = getNewProjectId(route.snapshot.params['projectId']);
    this.router.navigate([
      projectId, 
      this.router.url.substring(this.router.url.indexOf('/') + 1, this.router.url.length)
    ]);
  }
}

In case you need more granular control (basically, you have no clue what the current URL should look like), try traversing the route tree, processing the route config paths. You can find the :projectId configuration in there and based on where you are in the tree, you can understand your router.url structure.

let route = activatedRoute.snapshot;
while (route) {
  if (route.routeConfig && route.routeConfig.path) {
    // Do something with the path
  }
  route = route.parent;
}

Hope this helps a little :-)




回答5:


This is one way you can do it. Get the url, get the current params (because it sounds like you don't know what they are), if you have both projectid and userid then you route to the one with both. If the url ends in 'o' then you are on the /info route and if it ends in 's' then it is the /users route.

constructor(private activatedRoute: ActivatedRoute) {}

replacePrarm(projectId) {
  // get current url
  const url = this.router.url;

  // get current params
  this.activatedRoute.params.subscribe((params: Params) => {
       if(params['projectId'] && params['userId']) {
          router.navigate(projectId, 'users', params['userId'], 'profile'], {relativeTo: route});
       } else if (url[url.length - 1] === 'o') {
          router.navigate(projectId, 'info'], {relativeTo: route});
       } else if (url[url.length - 1] === 's') {
          router.navigate(projectId, 'users'], {relativeTo: route});
       }
  });
}

This is assuming you have no idea what route you are on, but in all reality you should have some idea if you are in users, info, or the profile. Otherwise you're using one component for three very different pages.




回答6:


In the corresponding component(i.e in .ts file) you need to add

import { Subscription } from 'rxjs/Subscription';

Uder into your @component use following

myVariable: {projectId: string, userId: string};
paramsSubscription: Subscription;


ngOnInit(){
this.myVariable = {
   projectId: this.route.snapshot.params['projectId'],
 // userId: this.route.snapshot.params['userId']
};
this.paramsSubscription = this.route.params
  .subscribe(
    (params: Params) => {
      this.myVariable.projectId = params['projectId'];
    //  this.myVariable.userId = params['userId'];
    }
  );
}

and on which method you are interested to change existing route.let's say you want to change route from following methods

changeRoute(): void{
   this.router.navigate(['/curentUrl',this.project_id_2, 'users/user_id_1/profile']);
}

hope this may helps you




回答7:


You can use:

this.router.navigate(
      [],
      {
        relativeTo: this.activatedRoute,
        queryParams: {projectId: 'project_id_2'},
        queryParamsHandling: "merge", // remove to replace all query params by provided
      });



回答8:


Since I also spent hours in investigating this question, I also want to share my solution.

I added a custom data item to the routes that should be able to switch between accountNames (projectIds in your case):

const routes: Routes = [
 {
   path: 'expenses/:accountName',
   component: ExpenseListComponent,
   data: { changeAccountUrl: ['expenses', ':accountName'] },
 }
];

This way it's easy for any component to check the activatedRoute's data for the presence of that item. If it's present, you can generate a route with it.

One more benefit is that you have more control about the generated routes.




回答9:


Using Angular 7, I achieved this by using a service that stores the current state of the router on every NavigationEnd. I can then traverse the state tree and construct an array of paths that can be used later to find and replace a param like :projectId.

Getting path array:

constructor(private router: Router) {
    this.router.events.subscribe(event => {
        if (event instanceof NavigationEnd) {
            this.pathArray = this.getPathArray(this.router.routerState.snapshot.root);
        }
    }
}

getPathArray(route: ActivatedRouteSnapshot) {
    let array = [];

    if (route.routeConfig && route.routeConfig.path !== '') {
        array.push(route.routeConfig.path);
    }

    if (route.firstChild) {
        array = array.concat(this.getPathArray(route.firstChild));
    }

    return array;
}

Replacing :projectId:

replacePathArrayId(id) {
    return this.pathArray.map(path => {
        return path.replace(':projectId', id);
    })
}

And using router.navigate(service.replacePathArrayId(id)) to actually change the route.



来源:https://stackoverflow.com/questions/50784299/angular-router-how-to-replace-param

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!