Маршрутизатор Angular2 зберігає рядок запиту


80

Я написав програму Angular2 (v2.0.1), яка використовує маршрутизатор. Веб-сайт завантажується кількома параметрами рядка запиту, тому повна URL-адреса спочатку виглядає так:

https://my.application.com/?param1=val1&param2=val2&param3=val3

У моїй конфігурації маршруту у мене є запис, який перенаправляє порожній маршрут:

const appRoutes: Routes = [
    {
        path: '',
        redirectTo: '/comp1',
        pathMatch: 'full'
    },
    {
        path: 'comp1',
        component: FirstComponent
    },
    {
        path: 'comp2',
        component: SecondComponent
    }
];

Моя проблема полягає в тому, що після завантаження програми URL-адреса вже не містить параметрів запиту, натомість вона виглядає так:

https://my.application.com/comp1

Чи є спосіб налаштувати маршрутизатор таким чином, щоб він зберігав початковий рядок запиту під час навігації?

Дякую
Лукасе

Відповіді:


67

Я не думаю, що існує спосіб визначити це в конфігурації маршрутів.

В даний час він підтримується для routerLinks та обов’язкової навігації для увімкнення

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

router.navigate(['/comp1'], { preserveQueryParams: true }); //deprecated. see update note
router.navigate(['/comp1'], { queryParamsHandling: "merge" });

Існує PR, щоб дозволити preserveQueryParamsглобальне налаштування .

Примітка щодо оновлення: з https://angular.io/api/router/NavigationExtras , saveQueryParams не підтримується, замість цього використовуйте queryParamsHandling


1
Де буде додано цей рядок коду? А чи можете ви пояснити "гвардію" на прикладі коду?
mattrowsboats

1
Я зробив це, але додавання захисту canActivate до порожнього рядка маршруту "перенаправлення" не підхоплюється.
mattrowsboats

2
Гаразд, але проблема все ще залишається при введенні програми. Якщо ви намагаєтеся "зловити" параметри URL-адреси після завантаження програми, це занадто пізно. Вони вже роздягнуті.
mattrowsboats

1
Через довгий час я виявив, що navigateByUrlце не працює. Краще використовувати navigateзавжди.
Картік

1
Мені шкода, що я проголосував проти, але для мене спрацювала лише відповідь AArias (Angular 9, якщо це актуально).
Arnaud P

51

Якщо ви використовуєте HTML-шаблон, тоді можете використовувати

<a [routerLink]="['/page-2']" [routerLinkActive]="['is-active']" queryParamsHandling="merge">

Щось, на що слід звернути увагу, це те, що параметр queryParamsHandling не має квадратних дужок.


1
це найкраща відповідь, і зауваження щодо дужок справді заощадило мені час
жаль

Рішення HTML - це те, що я насправді шукав. Дякую!
Дінеш Шекхават

ви можете використовувати з квадратними дужками: [queryParamsHandling] = "'merge'", що є основою кута, дужки означають "необхідне обчислення", тому замість "merge" вам потрібно написати рядок у "": "'merge'"
Юра

19

Виявляється, бездокументарний спосіб зробити це без інших хаків - це просто видалити провідну скісну риску в полі "redirectTo". Оскільки ви відповідаєте повному шляху, ви можете бути впевнені, що він буде робити те, що ви хочете (тобто відсутність сюрпризних сегментів url), і оскільки це вже не абсолютна ціль, Angular збереже поточні параметри запиту.

Так і в цьому випадку

{
  path: '',
  redirectTo: '/comp1',
  pathMatch: 'full'
}

стає:

{
  path: '',
  redirectTo: 'comp1',
  pathMatch: 'full'
}

Джерело: https://github.com/angular/angular/issues/13315


прибив це! Це єдиний шлях
Yazan Khalaileh

найпростіша відповідь
Рікардо,

12

Відповідь Гюнтера Цехбауера повинна спрацювати належним чином, але з якихось причин вона для мене взагалі не працює. У підсумку працюючим було передавання queryParamsбезпосередньо, а не «збереження» їх.

Ось як виглядає мій охоронець:

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    (...)
    this.router.navigate(['login'], { queryParams: route.queryParams });
}

Правильно, ця відповідь була єдиною, яка спрацювала і для мене
Арно П

3

Можливо, ви захочете здійснити пошук на https://github.com/angular/angular/issues із запитом на функцію, подібним до цього. Якщо жодного не існує, подайте запит на функцію.

Тим часом: я вважаю, вам потрібно буде створити компонент на шляху: '', з єдиною метою перенаправлення на '/ comp1', зберігаючи параметри QueryString.


Дякую, я ознайомлюсь із проблемами та подаю, якщо це буде потрібно.
Лукас Коллецкі

1

Провівши більшість відповідей, я це виявив

  • Відповідь Гюнтера Цехбауера для мене взагалі не працює
  • Пропозиція Крістофера усунути ведучого /теж не зробила цього
  • Відповідь AArias справді спрацювала, але призвела до додавання двох URL-адрес в історію:
    1. https://my.application.com/comp1?param=val <= (ಠ 益 ಠ)
    2. https://my.application.com/comp1;param=val

Отже, ось ще один підхід, який врешті-решт поводився відповідно до моїх очікувань:

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

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

    someMethod() {
        router.navigate(['/comp1', this.route.snapshot.params]);
    }
}

0

Якщо ви використовуєте HTML-шаблон, ви також можете використовувати preserveQueryParams="true"

Зверніть увагу, що preserveQueryParamsбез квадратної дужки.

Наприклад:

<a [routerLink]="['/navigate-to']" preserveQueryParams="true">


Відповідно до angular.io/api/router/NavigationExtras preserveQueryParams застаріло.
Cezary Tomczyk

0

Існує обхідний шлях використання вторинних маршрутів, оскільки Angular зберігатиме їх у первинній навігації маршрутом.

Спочатку додайте іменовану розетку маршрутизатора у верхній компонент:

<router-outlet name="params"><router-outlet>

Далі створіть фіктивний компонент для маршрутизації до:

@Component({
    template: ""
})
export class ParamsComponent {}

та визначте маршрут для створення екземпляра цього компонента до названої розетки:

{
    path: ':val1',
    component: ParamsComponent,
    outlet: "params"
}

Змініть навігацію в додатку на:

https://my.application.com/(params:val1)

Якщо ви подивитесь на будь-який ActivatedRoute, ви можете знайти маршрут "params", використовуючи:

  var paramsRoute = this.activatedRoute.route.children.find(r => r.outlet == "params");

Якщо paramsRoute має значення null, URL-адреса не містить (params: val1).

Ця наступна частина стає трохи "хакерською", оскільки вторинний маршрут створюється після первинного маршруту при початковому завантаженні. Через це, доки ваш додаток не буде повністю завантажений, ви можете виявити, що paramsRoute.snapshot має значення null. Існує приватна власність "_futureSnapshot", яка буде містити параметри маршруту при початковому запуску ... і зберігатиметься протягом життя програми. Ви можете дістатись до них, використовуючи:

var queryParams = 
      paramsRoute
      ? paramsRoute["_futureSnapshot"].params
      : {};
var val1 = queryParams["val1"];

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

if (paramsRoute) {
    paramsRoute.params.subscribe(params => {
        this.queryParams = params;
        this.loadData();
    });
} else {
    this.queryParams = {};
    this.loadData();
}

========= ЗМІНИ =============

Я знайшов ще кращий спосіб витягти параметри запиту, який, безумовно, НЕ icky ... У компонент або службу, яка створюється за допомогою екземпляра до того, як відбувається маршрутизація, додайте таку логіку:

    const routeRecognizedSubscription = this.router.events
        .filter(e => e instanceof RoutesRecognized)
        .subscribe((e: RoutesRecognized) => {
            const paramsRoute = e.state.root.children.find(r => r.outlet == "params");
            if (paramsRoute) {
                // capture or use paramsRoute.params 
            }
            routeRecognizedSubscription.unsubscribe();
        });

Цей код тимчасово підписується на RoutesRecognized події, які відбуваються перед навігацією. Отримавши першу подію, він автоматично скасує підписку, оскільки це потрібно зробити лише під час запуску програми.

На першій події ми шукаємо стан, що відповідає торговому пункту "params". Якщо знайдено, властивість params буде містити потрібні нам дані. Не потрібно отримувати доступ до приватної власності.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.