Кутова: Як оновити queryParams без зміни маршруту


126

Я намагаюся оновити (додати, видалити) queryParams з компонента. У angularJS це було можливо завдяки:

$location.search('f', 'filters[]'); // setter
$location.search()['filters[]'];    // getter

У мене є додаток зі списком, який користувач може фільтрувати, замовляти тощо, і я хотів би встановити у queryParams URL-адреси всі активовані фільтри, щоб він міг скопіювати / вставити URL або поділитися ним з кимось іншим.

Однак я не хочу, щоб моя сторінка перезавантажувалася щоразу, коли вибрано фільтр.

Це можливо зробити з новим маршрутизатором?

Відповіді:


272

Ви можете перейти до поточного маршруту за допомогою нових параметрів запитів, які не перезавантажать вашу сторінку, але оновлять параметри запитів.

Щось на зразок (у складі):

constructor(private router: Router) { }

public myMethodChangingQueryParams() {
  const queryParams: Params = { myParam: 'myNewValue' };

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

Зауважте, що, хоча вона не перезавантажить сторінку, це підштовхне новий запис до історії браузера. Якщо ви хочете замінити його в історії замість того, щоб додавати там нове значення, ви можете використовувати { queryParams: queryParams, replaceUrl: true }.

EDIT: Як уже вказувалося в коментарях, []і relativeToвластивість відсутня в моєму первісному прикладі, тому вона могла змінити і маршрут, а не лише параметри запитів. Правильне this.router.navigateвикористання буде в цьому випадку:

this.router.navigate(
  [], 
  {
    relativeTo: this.activatedRoute,
    queryParams: { myParam: 'myNewValue' },
    queryParamsHandling: 'merge'
  });

Якщо встановити нове значення параметра null, вилучите параметр з URL-адреси.


30
Мені довелося використовувати []замість того, ['.']щоб це спрацювало
Хайме Гомес

5
Потрібно використовувати queryParams ['relaTo'] = this.activateRoute; зробити навігацію відносно поточної сторінки
klonq

3
Приємне рішення для вирішення проблеми ОП. Те, що вас не отримує, якщо я чогось не пропускаю, - це можливість рухатися назад і вперед в історії вашої поточної сторінки (наприклад, змінити фільтр або замовити 5 разів, кожен з яких має власну URL-адресу, але такий же компонент) і мати Вміст сторінки відображається як би це було, якби ви зверталися безпосередньо до цих 5 URL-адрес. Я думаю, ви могли б зробити це вручну за допомогою this.activatedRoute.queryParams.subscribeі зробити різні оновлення у своєму компоненті, але чи є простий кутовий спосіб просто завантажити маршрут таким чином, щоб назад і вперед працювали автоматично?
jmq

1
при використанні router.navigate він буде прокручуватися вгорі вікна, будь-які ідеї, як це відключити?
Хесе

1
@Hese, ви впевнені? Я не думаю, що вона прокрутить до вершини. Погляньте на цей приклад: stackblitz.com/edit/angular-sdtsew?file=src/app/…
Radosław Roszkowiak

23

@ Радослав Рошковіак відповідь майже правильна, за винятком того, що relativeTo: this.routeпотрібно, як зазначено нижче:

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

changeQuery() {
  this.router.navigate(['.'], { relativeTo: this.route, queryParams: { ... }});
}

14

У Angular 5 ви можете легко отримати та змінити копію urlTree, проаналізувавши поточний URL. Сюди ввійдуть параметри запитів та фрагменти.

  let urlTree = this.router.parseUrl(this.router.url);
  urlTree.queryParams['newParamKey'] = 'newValue';

  this.router.navigateByUrl(urlTree); 

"Правильний спосіб" змінити параметр запиту, ймовірно, з createUrlTree, як показано нижче, який створює нове UrlTree з поточного, дозволяючи нам змінювати його за допомогою NavigationExtras .

import { Router } from '@angular/router';

constructor(private router: Router) { }

appendAQueryParam() {

  const urlTree = this.router.createUrlTree([], {
    queryParams: { newParamKey: 'newValue' },
    queryParamsHandling: "merge",
    preserveFragment: true });

  this.router.navigateByUrl(urlTree); 
}

Щоб видалити параметр запиту таким чином, ви можете встановити його на undefinedабо null.


2
navigateByUrlвідрізняється navigate- не лише парам UrlTree. Див stackoverflow.com/a/45025432/271012
Drenai

9

Спробуйте

this.router.navigate([], { 
  queryParams: {
    query: value
  }
});

буде працювати для тієї ж маршрутної навігації, крім одиничних лапок.


Я шукав саме цю річ. Дякую!!!
cevaris

7

Відповідь з більшістю голосів частково працювала для мене. URL-адреса браузера залишилася колишньою, але routerLinkActiveпісля навігації мій більше не працював.

Моє рішення було використовувати lotation.go:

import { Component } from "@angular/core";
import { Location } from "@angular/common";
import { HttpParams } from "@angular/common/http";

export class whateverComponent {
  constructor(private readonly location: Location, private readonly router: Router) {}

  addQueryString() {
    const params = new HttpParams();
    params.append("param1", "value1");
    params.append("param2", "value2");
    this.location.go(this.router.url.split("?")[0], params.toString());
  }
}

Я використовував HttpParams для створення рядка запиту, оскільки вже використовував його для надсилання інформації з httpClient. але ви можете просто побудувати його самостійно.

і this._router.url.split("?")[0], - це видалити весь попередній рядок запиту з поточної URL-адреси.


4
ЦЕ БУДЕ прийнято відповідь, router.navigates також оновлює ngOnit, location.go НЕ робить цього! Це дуже важливо, тому що якщо ваш компонент виконує якусь логіку ngOnit (HTTP-дзвінки тощо), вони будуть викликатися знову, коли ви використовуєте router.navigate. Ви цього не хочете.
Danny Hoeve

Навіщо потрібен маршрутизатор, лише для URL-адреси? Чи не this.location.path().split...краще?
Володимир

@ Владимир, ви можете мати рацію, я використовував це для інших цілей у своєму компоненті, тому це було не тільки для цього. Я не маю часу перевірити.
moi_meme

Це не спрацює, якщо ви хочете зберегти параметри запиту, наприклад, параметри просування або відстеження google
Jon

5

Я закінчила поєднання urlTreeзlocation.go

const urlTree = this.router.createUrlTree([], {
       relativeTo: this.route,
       queryParams: {
           newParam: myNewParam,
       },
       queryParamsHandling: 'merge',
    });

    this.location.go(urlTree.toString());

Не впевнений, чи toStringможе це викликати проблеми, але, на жаль location.go, здається, що він базується на рядках


4

Якщо ви хочете змінити параметри запиту без зміни маршруту. див. нижче приклад може допомогти вам: поточний маршрут: / пошук і цільовий маршрут (без сторінки для перезавантаження): / пошук? query = love

submit(value: string) {
{ this.router.navigate( ['.'],  { queryParams: { query: value } })
    .then(_ => this.search(q));
}
search(keyword:any) { 
//do some activity using }

зверніть увагу: ви можете використовувати this.router.navigate (['пошук'] замість цього.router.navigate (['.']


Я не впевнений, що [.] Кращий підхід, ніж relativeTo:, але .then()корисний був - не знав, що навігація () повернула обіцянку, так що раді, що ви написали!
Дренай

0

Спочатку нам потрібно імпортувати модуль маршрутизатора з кутового маршрутизатора та оголосити його ім’я псевдоніма

import { Router } from '@angular/router'; ---> import
class AbcComponent implements OnInit(){
constructor(
    private router: Router ---> decalre alias name
  ) { }
}

1. Ви можете змінити параметри запитів за допомогою функції "router.navigate" та передати параметри запиту

this.router.navigate([], { queryParams: {_id: "abc", day: "1", name: "dfd"} 
});

Він оновить параметри запитів у поточному, тобто активованому маршруті

  1. Нижче буде переспрямовано сторінку abc з _id, днем ​​та назвою як параметри запитів

    this.router.navigate (['/ abc'], {queryParams: {_id: "abc", день: "1", назва: "dfd"}});

    Він оновить параметри запитів у маршруті "abc" разом із трьома параметрами запиту

Для отримання параметрів запитів: -

    import { ActivatedRoute } from '@angular/router'; //import activated routed

    export class ABC implements OnInit {

    constructor(
        private route: ActivatedRoute //declare its alias name
      ) {}

    ngOnInit(){
       console.log(this.route.snapshot.queryParamMap.get('_id')); //this will fetch the query params
    }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.