在Angular 2中更改当前路由上的单个路由参数

29

是否可以在保留所有其他参数的同时更改当前路由中的单个路由参数?这是用于分页组件,该组件将路由到新页面,同时保留当前路由的其他部分。

以下是一些示例:

  • 从默认页面转到第二页:orders?foo=foo&bar=bar > orders?foo=foo&bar=bar&page=2
  • 从默认页面转到第二页(子级):orders/;foo=foo;bar=bar > orders/;foo=foo;bar=bar;page=2
  • 在具有参数的子级和父级上将第二页转到第三页:orders/;foo=foo;page=2?bar=bar > orders/;foo=foo;page=3?bar=bar

我尝试使用routerLink,但这会丢失任何不是最初作为路由器链接的一部分的其他参数。

我还尝试使用当前的Router来获取当前路径的Instruction,但更改Instruction的参数在调用navigateByInstruction()时似乎没有任何效果。

6个回答

3
如果activeRoute能够返回当前路由的简单克隆[],以便在调用router.navigate(nextroutearray)之前进行操作,那就太好了,但我在api中没有找到这样的方法。因此,我将需求集中到一个简单的服务中,在那里我可以解析当前的activeRoute和一组参数,以用于下一个路由。我不认为这段代码会涵盖路由中url的所有复杂性,但在我的情况下,我只在路由的最后一部分使用参数,所以它对我有效。该服务方法如下:
routeFor(activeRoute: ActivatedRoute, params: any): any[] {
    let result = [];
    result.push('/');
    for (var i = 0; i < activeRoute.pathFromRoot.length; i++) {
        activeRoute.pathFromRoot[i].snapshot.url.forEach(r => result.push(r.path));
    }

    let currentParams = activeRoute.pathFromRoot[activeRoute.pathFromRoot.length - 1].snapshot.url[0].parameters;
    for (var n in currentParams) {
        if (currentParams.hasOwnProperty(n) && !params.hasOwnProperty(n)) {
            params[n] = currentParams[n];
        }
    }

    result.push(params);
    return result;
}

然后,我可以在任何组件中使用此方法,注入我的站点地图服务:
setNextTab(tab: string) {
    let nextUrl = this.sitemapService.routeFor(this.activatedRoute, { pagetab: tab });
    this.router.navigate(nextUrl);
}

在 HTML 中,调用 setNextTab 方法的链接如下所示:
  • 下一个标签页

  • 2
    您可以使用查询参数选项而不是参数,它的使用方式如下:
    在调用组件中使用。
    const navigationExtras: NavigationExtras = {
      queryParams: { 'param_id': 1, 'param_ids': 2, 'list':[1,2,3] },
    };
    this.router.navigate(['/path'], navigationExtras);
    

    在所调用的组件中。
      this.route.queryParamMap.map(params =>  params.get('param_id') || 
        'None').subscribe(v => console.log(v));
      this.route.queryParamMap.map(params =>  params.get('param_ids') || 
            'None').subscribe(v => console.log(v));
      this.route.queryParamMap.map(params =>  params.getAll('list') || 
                'None').subscribe(v => console.log(v));
    

    2
    constructor(private router: Router, private route: ActivatedRoute) {}
    
    this.router.navigate(['./'],{relativeTo: this.route, queryParams:  {key:"value"});
    

    在回答中添加一些内容,而不仅仅是代码片段,以解释您想要添加到主题中的内容或者您的答案与其他答案的区别。 - H3AR7B3A7
    此答案被标记为低质量,可能需要解释。以下是如何编写好答案的指南How do I write a good answer?。仅包含代码的答案不被认为是好答案,并且很可能会由于对学习者社区没有帮助而被取消投票或删除。这只是对你来说很明显,请解释一下它的作用,以及它与现有答案的区别/更好之处。 来自审核 - Trenton McKinney

    0
    为什么你不直接这样做:
    <a [routerLink]="['./Cmp', {limit: 10, offset: 10}]">Previous Page</a>
    <a [routerLink]="['./Cmp', {limit: 10, offset: 20}]">Next Page</a>
    

    2
    分页组件将在多个地方重复使用,因此需要传递给routerLink的参数是未知的。这也会丢失自添加以来的任何其他路由参数(例如,附加过滤器)。 - Robert Davey

    0

    这很容易。假设我们在ListComponent中有一个方法,它可以更改页面并保留所有其他参数不变(例如与搜索相关的参数-不能更改页面并忘记我们正在搜索某些内容:):

    page (page) {
        this.list.page = page;
        this._router.navigate([this.list.route, _.assign(this._params.params, { page: page })]);
        this.update(); // Update your list of items here
    }
    

    我使用Underscore将页面参数分配给来自私有注入的RouteParams对象的现有参数映射。该映射在导航时更新,所以一切都很好,只需记住您不能直接更改它,因为它是不可变的。

    这是我的文章列表实现,以及用作指令提供分页的分页组件:

    ArticleListComponent:

    @Component({
        selector: 'articles',
        templateUrl: './article/list/index.html',
        directives: [PaginationComponent],
        providers: [ArticleService]
    })
    export class ArticleListComponent implements OnInit {
        list: ArticleList = new ArticleList;
    
        private _urlSearchParams: URLSearchParams = new URLSearchParams;
    
        constructor (
            private _article: ArticleService,
            private _router: Router,
            private _params: RouteParams,
            private _observable: ObservableUtilities
        ) {}
    
        update () {
            this._observable.subscribe(this._article.retrieveRange(this.list));
        }
    
        ngOnInit () {
            let page = this._params.get("page");
            if(page) {
                this.list.page = Number(page);
            }
    
            // check for size in cookie 'articles-per-page'
    
            let title = this._params.get("title");
            if (title) {
                this.list.title = title;
            }
    
            this.update();
        }
    
        size (size: number) {
            // set cookie 'articles-per-page'
        }
    
        page (page) {
            this.list.page = page;
            this._router.navigate([this.list.route, _.assign(this._params.params, { page: page })]);
            this.update();
        }
    
        search () {
            this.list.page = 1;
            let params = _.pick({
                title: this.list.title
            }, _.identity);
            this._router.navigate([this.list.route, params ]);
        }
    }
    

    分页组件:

    import { Component, Input, Output, EventEmitter, OnInit } from 'angular2/core';
    import { RouteParams } from 'angular2/router';
    import  _ from 'underscore';
    
    import { List } from '../common/abstract';
    
    @Component({
        selector: 'pagination',
        templateUrl: './pagination/index.html'
    })
    export class PaginationComponent implements OnInit {
        @Input() list: List;
        @Output() change  = new EventEmitter<number>();
    
        pages: Array<number> = [];
    
        constructor(
            private _params: RouteParams
        ) {}
    
        ngOnInit () {
            this.pages = _.range(1, this.list.pages + 1);
        }
    
        onClick (page: number) {
            if (page > 0 && page <= this.list.pages) {
                this.change.emit(page);
            }
            return false;
        }
    
        href (page: number) {
            return `${this.list.uri}?${_.map(_.assign(this._params.params, { page: page }), (value, param) => `${param}=${value}`).join('&')}`;
        }
    
        first (page) {
            return page == 1 ? 1 : null;
        }
    
        last(page) {
            return page == this.list.pages ? this.list.pages : null;
        }
    }
    

    分页模板(index.html)- 我使用Bootstrap进行样式设计

    <div>
            <ul class="pagination">
                <li [class.disabled]="first(list.page)"><a (click)="onClick(list.page - 1)" [attr.href]="href(list.page - 1)">&laquo;</a></li>
    
                <template ngFor let-page [ngForOf]="pages">
                    <li *ngIf="(page >= list.page - 2 && page <= list.page + 2) || first(page) || last(page)" [ngSwitch]="(page != list.page - 2 && page != list.page + 2) || first(page) || last(page)" [class.active]="page == list.page">
                        <a *ngSwitchWhen="true" (click)="onClick(page)" [attr.href]="href(page)">{{page}}</a>
                        <a *ngSwitchDefault (click)="onClick(page)" [attr.href]="href(page)">...</a>
                    </li>
                </template>
    
                <li [class.disabled]="last(list.page)"><a (click)="onClick(list.page + 1)" [attr.href]="href(list.page + 1)">&raquo;</a></li>
            </ul>
        </div>
    

    在文章列表模板中的使用方法:

    ...
    <pagination *ngIf="list.pages > 1" [(list)]="list" (change)="page($event)" class="text-center"></pagination>
    ...
    

    在我的小项目中,文章服务使用 Range header 从服务器请求一系列文章。

    希望您会觉得这很有帮助!


    0

    使用if语句switch case语句来推送参数

    if(yourchild == child1){
        params = { 
          parameter1: parameter1, 
          parameter2: parameter2,
        }
    } else (yourchild == child2){
        params = { 
          parameter1: parameter1, 
          parameter2: parameter2,
          parameter3: parameter3
        }
    }
    this.router.navigate([`/yourparent/${yourchild}`], { queryParams: params });
    

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接