Измените один параметр маршрута на текущем маршруте в Angular 2

Можно ли изменить один параметр маршрута в текущем маршруте, сохранив при этом все остальные параметры? Это для использования в компоненте пейджинга, который будет перенаправляться на новую страницу, сохраняя при этом другие части текущего маршрута такими же.

Несколько примеров:

  • Страница по умолчанию на страницу 2: orders?foo=foo&bar=bar > orders?foo=foo&bar=bar&page=2
  • Страница по умолчанию на страницу 2 (дочерняя): orders/;foo=foo;bar=bar > orders/;foo=foo;bar=bar;page=2
  • Страница 2–3 для дочернего и родительского элементов с параметрами: orders/;foo=foo;page=2?bar=bar > orders/;foo=foo;page=3?bar=bar

Я пытался использовать routerLink, однако при этом теряются все дополнительные параметры, которые изначально не являются частью ссылки на маршрутизатор.

Я также пытался использовать текущий Router, чтобы получить Instruction для текущего пути, однако изменение параметров Instruction, похоже, не имеет никакого эффекта при вызове navigateByInstruction().


person Robert Davey    schedule 29.01.2016    source источник


Ответы (5)


Было бы неплохо, если бы activeRoute мог возвращать простой клон текущего маршрута [], которым можно было бы манипулировать перед вызовом router.navigate(nextroutearray), но я не нашел такого метода в API.

Поэтому я сосредоточил требование в простой службе, где я могу проанализировать текущий активный маршрут + набор параметров, которые будут использоваться для следующего маршрута. Я не думаю, что этот код покроет всю сложность 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 выглядит так:

<li (click)="setNextTab('myTabName')">Next tab</li>

person Kjeld Poulsen    schedule 17.12.2017

вы можете использовать параметр параметра запроса вместо параметра, который он использует, например

в вызывающем компоненте

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));
person Sunil Kumar    schedule 01.09.2017

Почему вы просто не делаете этого:

<a [routerLink]="['./Cmp', {limit: 10, offset: 10}]">Previous Page</a>
<a [routerLink]="['./Cmp', {limit: 10, offset: 20}]">Next Page</a>
person Vlado Tesanovic    schedule 29.01.2016
comment
Компонент пейджинга будет повторно использоваться в ряде мест, поэтому параметры, которые необходимо передать в routerLink, неизвестны. Это также приведет к потере любых дополнительных параметров маршрута, которые были добавлены с тех пор (например, дополнительные фильтры). - person Robert Davey; 29.01.2016

Это довольно легко. Допустим, у нас есть метод в нашем компоненте 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. Эта карта обновляется при навигации, так что у нас все хорошо, просто помните, что вы не можете изменить ее напрямую, она неизменна.

Вот моя реализация списка статей вместе с компонентом нумерации страниц, используемым в качестве директивы для обеспечения нумерации страниц:

Компонент списка статей:

@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) — я использую бутстрап для стилизации

<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.

Надеюсь, вы найдете это полезным!

person Kesarion    schedule 22.05.2016

используйте оператор if или переключатель регистра для передачи параметров

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 });
person Steve Nginyo    schedule 30.11.2020