角度路由器:如何替换param?

时间:2018-06-10 13:42:22

标签: angular angular2-routing angular-routing

我们假设我有3个网址: /:projectId/info/:projectId/users/:projectId/users/:userId/profile。所有人都有param projectId。 UI有一个组件可以从一个项目切换到另一个项目。所以我需要:

  1. 获取当前网址
  2. 按名称更改参数(例如projectId)
  3. 导航到新网址
  4. 所以我需要类似this.router.replaceParam(currentUrl, {projectId: 'project_id_2'})的内容,它会将/project_id_1/users/user_id_1/profile转换为/project_id_2/users/user_id_1/profile(以及:projectId param的任何其他网址

    我认为这是一个简单而常见的问题,但在1小时内没有找到解决方案。建议的here解决方案无效,如上一条评论中所述

13 个答案:

答案 0 :(得分:2)

您可以使用HTML或Ts

  

1>在HTML中

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

  

2>在Typescript

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

答案 1 :(得分:2)

要从当前网址导航到特定链接,您可以执行以下操作

 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
 }

在ngOnInit函数中,我们订阅了params,因此我们可以观察并执行url参数中任何更改的语句。

答案 2 :(得分:0)

查看您的问题,您想要更改2个参数。

如下所述:

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

您可以实施router.navigate([yourprojectId, 'users', youruserId , 'profile'], {relativeTo: route});

答案 3 :(得分:0)

这会有帮助吗?

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)
    ]);
  }
}

如果您需要更精细的控制(基本上,您不知道当前URL应该是什么样子),请尝试遍历路由树,处理路由配置路径。您可以在其中找到:projectId配置,并根据您在树中的位置,了解您的router.url结构。

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

希望这有点帮助: - )

答案 4 :(得分:0)

这是你可以做到的一种方式。获取网址,获取当前的参数(因为它听起来你不知道它们是什么),如果你同时拥有projectid和userid,那么你将路由到两者。如果网址以#include <stdio.h> #include <stdlib.h> #include <ctype.h> int main() { char* c; scanf(" %c", c); printf("%c\n", *c); return 0; } 结尾,那么您就在'o'路线上,如果它以/info结尾,那么它就是's'路线。

/users

这假设你不知道你在哪条路线上,但在所有现实中你应该知道你是否在用户,信息或个人资料中。否则,您将一个组件用于三个截然不同的页面。

答案 5 :(得分:0)

在相应的组件中(即.ts文件中),您需要添加

import { Subscription } from 'rxjs/Subscription';

使用

进入你的@component
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'];
    }
  );
}

以及您有兴趣更改现有route.let的方法,假设您想要从以下方法更改路线

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

希望这可以帮助你

答案 6 :(得分:0)

您可以使用:

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

答案 7 :(得分:0)

由于我还花了几个小时研究这个问题,所以我也想分享我的解决方案。

我在路由中添加了一个自定义数据项,该数据项应能够在accountNames(您的情况下为projectIds)之间进行切换:

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

这样,任何组件都可以很容易地检查ActivatedRoute的数据是否存在该项目。如果存在,则可以使用它生成一条路线。

另一个好处是您可以更好地控制生成的路线。

答案 8 :(得分:0)

使用Angular 7,我通过使用在每个NavigationEnd上存储路由器当前状态的服务来实现这一点。然后,我可以遍历状态树并构造一个路径数组,以后可用于查找和替换:projectId之类的参数。

获取路径数组:

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;
}

替换:projectId

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

并使用router.navigate(service.replacePathArrayId(id))实际更改路线。

答案 9 :(得分:0)

我今天面对角度9的问题。 就我而言,我遇到了树形网址情形:

  1. something/i-ignore/../my-path 我在其中显示预定义值(例如:最新值)
  2. something/i-ignore/../my-path-> something/i-ignore/../my-path/1 我明确要求从基本网址开始的/1资源
  3. something/i-ignore/../my-path/1-> something/i-ignore/../my-path/2 我在哪里更改请求的资源

一种有趣的方法是proposed by Omkar Jadhav,他以编程方式从ActivatedRoute向后退了一步

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

我对参数更改事件做出了反应,使用了code proposed by Michael

的简化版本
this._route.params
  .subscribe((params) => {
    console.log(params) // prints {resourceId: "1"}
  });

结合以上所述,我可以开始处理案例2和案例3。

const url = this.router.url.split('my-path');
if (url[1] && 0 < url[1].length) {
  this.router.navigate(['../' + this.newResourceId],{relativeTo: this.activatedRoute});
} else {
  this.router.navigate([this.newResourceId], {relativeTo: this.activatedRoute});
}

然后我只需要订阅参数

this.activatedRoute.params.subscribe(params => this.getResource(params['resourceId']));

完整代码:

ngOnInit(): void {
    this.activatedRoute.params.subscribe(params => this.getResource(params['resourceId']));
    this.getResource(this.activatedRoute.snapshot.params?.resourceId);
}

resourceRequestEvent(resourceId: number) {
    // this will trigger the page refresh
    const url = this.router.url.split('my-path');
    if (url[1] && 0 < url[1].length) {
        this.router.navigate(['../' + resourceId], {relativeTo: this.activatedRoute});
    } else {
        this.router.navigate([resourceId], {relativeTo: this.activatedRoute});
    }
}

答案 10 :(得分:0)

此服务将使用当前路由配置重建当前网址。它的工作原理是重建网址段,并用参数中的匹配键替换以:开头的段

要更新当前网址,您只需调用方法

this.routingService.updateRoute({id: 123})
import { Injectable } from '@angular/core';
import { ActivatedRoute, NavigationEnd, Params, Router } from '@angular/router';
import { Subject } from 'rxjs';
import { filter } from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})
export class RoutingService {
  routeChange: Subject<void> = new Subject<void>();
  params: Params;

  constructor(
    private router: Router,
    private activatedRoute: ActivatedRoute
  ) {
    this.router.events
      .pipe(filter(event => event instanceof NavigationEnd))
      .subscribe(() => {
        this.params = this.activatedRoute.firstChild.snapshot.params;
        this.routeChange.next();
      });
  }


  updateRoute(data: { [key: string]: string | number }) {
    const params = { ... this.params, ...data };
    const segments = this.activatedRoute.firstChild.snapshot.routeConfig.path.split('/');
    const commands = segments.map(v => v.indexOf(':') === 0 ? params[v.substr(1)] : v);
    if (commands.join('/') !== this.activatedRoute.firstChild.snapshot.url.join()) {
      return this.router.navigate(commands);
    }
  }
}

答案 11 :(得分:0)

这将采用一个 url 字符串并更新 params 对象中的所有参数:

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

setRouteParams(url: string, route: ActivatedRoute, params: any): string {
  for (const p in params)  {
    const old = route.snapshot.paramMap.get(p);
    url = url.replace(`/${old}/`, `/${params[p]}/`);
  }
  return url;
}

它遍历 params 的属性,从当前路由中获取每个属性 p 的当前值,然后将其替换为属性 params[p] 的值。我们想知道当前的路由参数值,以便我们知道需要替换什么。匹配 /${old}/ 而不是 old 将避免在 /aa/ 中想用 /bb/ 替换 /aad/aa/ 而得到 /bbd/aa/ 的情况。

可以这样调用setRouteParams('/project_id_1/users/user_id_1/profile', this.activatedRoute, {projectId: 'project_id_2')

这不会处理像 /11/users/11/profile/params {userId: '22'} 这样的路由。它将代替 projectId。为了处理这种情况,我们需要知道参数 {userId: {value: '22', position: 3}} 的顺序(基于 1 的位置,因为下面的第一段将是空字符串)。

setRouteParams(url: string, params: any): string {
  const segments = url.split('/');
  for (const p in params)  {
    segments[params[p].position] = params[p].value;
  }
  return segments.join('/');
}

如果你想同时导航:

setRouteParamsAndNavigate(router: Router, params: any): void {
  const segments = router.url.split('/');
  for (const p in params)  {
    segments[params[p].position] = params[p].value;
  }
  router.navigateByUrl(segments.join('/')).then(() => {});
}

答案 12 :(得分:0)

为了让@khush 的回答更加完整并解决需要 id 唯一的问题,我做了以下调整:

id: string;

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

ngOnInit() {
    this.route.params.subscribe(params => {
        this.id = params['id'];    
    });
}

navigate() {
    this.router.navigateByUrl(this.router.url.replace(`/${this.id}/`, `/${newId}/`));
}