Як отримати параметри запиту з URL у Angular 2?


237

Я використовую angular2.0.0-beta.7. Коли компонент завантажується на шлях, на який /path?query=value1він перенаправлений /path. Чому параметри GET були вилучені? Як я можу зберегти параметри?

У мене є помилка в маршрутизаторах. Якщо у мене є основний маршрут, як

@RouteConfig([
  {
      path: '/todos/...',
      name: 'TodoMain',
      component: TodoMainComponent
  }
])

і моєму дитячому маршруту подобається

@RouteConfig([
  { path: '/', component: TodoListComponent, name: 'TodoList', useAsDefault:true },
  { path: '/:id', component: TodoDetailComponent, name:'TodoDetail' }
])

тоді я не можу отримати парами в TodoListComponent. Я вмію дістати

params("/my/path;param1=value1;param2=value2") 

але я хочу класичне

query params("/my/path?param1=value1&param2=value2")

1
як ви вказали @RouteConfigдля цього path?
Pankaj Parkar

Я виявив помилку. У мене є основний маршрут і дочірній маршрут, і якщо у мене є основний маршрут, як {path: '/ todos / ...', name: 'TodoMain', компонент: TodoMainComponent} і дочірній маршрут {path: '/', компонент: TodoListComponent, name: 'TodoList', useAsDefault: true}, це не працює і перенаправляє на URL без парамерів запитів.
FireGM

Відповіді:


412

Вводячи екземпляр ActivatedRouteодного, можна підписатись на різні види спостереження, включаючи а queryParamsта paramsспостережувані:

import {Router, ActivatedRoute, Params} from '@angular/router';
import {OnInit, Component} from '@angular/core';

@Component({...})
export class MyComponent implements OnInit {

  constructor(private activatedRoute: ActivatedRoute) {}

  ngOnInit() {
    // Note: Below 'queryParams' can be replaced with 'params' depending on your requirements
    this.activatedRoute.queryParams.subscribe(params => {
        const userId = params['userId'];
        console.log(userId);
      });
  }

}

ПРИМІТКА ПРО ВІДПОВІДАЛЬНІСТЬ

@Reto та @ codef0rmer цілком справедливо зазначили, що, згідно з офіційними документами, метод unsubscribe()внутрішніх компонентів onDestroy()у цьому випадку є непотрібним. Це було видалено з мого зразка коду. (див. синє поле попередження в цьому підручнику)


2
Далі пропоную замінити підписку на обіцянку - у цьому спеціальному випадку. this.activateRoute.params.toPromise () .then (відповідь => ...) .catch (помилка => ...);
грудня

Де я можу пройти "activeRoute"?
michali

20
З офіційної документації: Чи потрібно скасовувати підписку? The Router manages the observables it provides and localizes the subscriptions. The subscriptions are cleaned up when the component is destroyed, protecting against memory leaks, so we don't need to unsubscribe from the route params Observable.
Ретро

кутові переадресації без запуску підписки (або обіцянки). Я бачу оригінальний зворотний виклик oAUth з маркером, але потім він перенаправляє на маршрут без парами запитів, а console.log (param) - просто порожній об'єкт.
FlavorScape

1
@Sobhan, так, є різниця. Оператор switchMap повертає спостережуване, тоді як оператор підписки дозволяє спостерігачеві (нашому компоненту) бачити елементи, які в кінцевому підсумку випускаються спостережуваним. Тож у документах використовуються два екземпляри комутаційної карти. 1) Вони використовували switchMap для додавання запиту на герої. SwitchMap, на відміну від підписки, забезпечить скасування запиту у випадку, якщо користувач повторно перейде до маршруту, зберігаючи героя. 2) Використовується асинхронна труба. Асинхронні труби споживають спостережуване, тому не слід підписуватися (Async труба зробить це за вас).
Стівен Пол

103

Коли така URL-адреса, як ця http://stackoverflow.com?param1=value

Ви можете отримати param1 за кодом наступним чином:

import { Component, OnInit } from '@angular/core';
import { Router, ActivatedRoute, Params } from '@angular/router';

@Component({
    selector: '',
    templateUrl: './abc.html',
    styleUrls: ['./abc.less']
})
export class AbcComponent implements OnInit {
    constructor(private route: ActivatedRoute) { }

    ngOnInit() {
        // get param
        let param1 = this.route.snapshot.queryParams["param1"];
    }
}

2
це означає, що вам більше не потрібно додавати "/: id" у шлях routeconfig? тому що я отримую "невизначений", коли це використовую, тому я все-таки повинен десь
помилитися

2
Чудово. Це я шукав, тому що мені потрібно читати парами безпосередньо з URL-адреси динамічного сервера. Я не можу використовувати навігацію.
The.Bear

37

Незважаючи на те, що питання визначає версію бета-версії 7 , це запитання також з’являється як головний результат пошуку в Google для поширених фраз, таких як кутові параметри 2 запиту . З цієї причини ось відповідь на найновіший маршрутизатор (зараз в альфа-7 ).

Те, як читаються парами, різко змінилося. Спочатку потрібно ввести залежність, яку викликають Routerу конструкторі такі параметри, як:

constructor(private router: Router) { }

і після цього ми можемо підписатись на параметри запиту в нашому ngOnInitметоді (конструктор теж добре, але його ngOnInitслід використовувати для перевірки), наприклад

this.router
  .routerState
  .queryParams
  .subscribe(params => {
    this.selectedId = +params['id'];
  });

У цьому прикладі ми читаємо ідентифікатор парами запиту з подібної URL-адреси example.com?id=41.

Є ще мало чого помітити:

  1. Доступ до властивості paramsтипу params['id']завжди повертає рядок , і це можна перетворити на число шляхом префіксації +.
  2. Причина, за якою парами запиту вибираються із спостережуваного, полягає в тому, що він дозволяє повторно використовувати один і той же екземпляр компонента замість завантаження нового. Кожен раз, коли параметр запиту змінюється, це спричинить нову подію, на яку ми підписалися, і, таким чином, ми можемо відповідно реагувати на зміни.

Чи існує спосіб, щоб декілька параметрів переходили до одного члена? Наприклад, я хотів би або "id", або "ідентифікація" перейшов до цього.selectedId.
phandinhlan

@phandinhlan: Ну, це насправді не питання, пов'язане з кутовим 2. Це, звичайно, можна реалізувати, але вам потрібно визначити логіку самостійно. В основному те, що ви хочете зробити, - це спочатку перевірити, чи визначено перший ключ, і лише потім прочитати значення з нього, а якщо ні, прочитайте значення за допомогою іншого ключа. Цього можна досягти чимось подібним if (params.hasOwnProperty('id')) { this.selectedId = params['id'] } else { this.selectedId = params['identification']}.
Roope Hakulinen

Так, я закінчила щось подібне. Я просто думав, що існують такі "побудовані" способи, як: this.selectedId = + params ['id']; this.selectedId = + params ['ідентифікація']; Звичайно, це не має ніякого сенсу і не працює.
phandinhlan

28

Мені дуже сподобалась відповідь @ StevePaul, але ми можемо зробити те ж саме, що не має сторонніх підписок / скасування підписки.

import { ActivatedRoute } from '@angular/router';
constructor(private activatedRoute: ActivatedRoute) {
    let params: any = this.activatedRoute.snapshot.params;
    console.log(params.id);
    // or shortcut Type Casting
    // (<any> this.activatedRoute.snapshot.params).id
}

7
Застереження, звичайно, з цим - це те, що воно буде початковим значенням і наступні зміни не відображатимуться. Тож якщо ви змінюєте параметри URL-адреси програмно як частину своєї логіки, це те, що вам потрібно знати
ambidexterous

Не впевнений, чи змінилося це з пізнішими версіями Angular, але тепер я бачу це у this.activateRoute.snapshot.queryParams
Michael

21

Надіслати параметри запитів

import { Router } from '@angular/router';
this.router.navigate([ '/your-route' ], { queryParams: { key: va1, keyN: valN } });

Отримувати параметри запитів

import { ActivatedRoute } from '@angular/router';
this.activatedRoute.queryParams.subscribe(params => {
    let value_1 = params['key'];
    let value_N = params['keyN'];
});

Офіційне джерело


Читання працює чудово. Але воно враховує регістри. Як ми можемо зробити його нечутливим?
Unnie

12

Привіт, ви можете використовувати URLSearchParams, більше про це ви можете прочитати тут .

імпорт:

import {URLSearchParams} from "@angular/http";

і функція:

getParam(){
  let params = new URLSearchParams(window.location.search);
  let someParam = params.get('someParam');
  return someParam;
}

Примітка . Він підтримується не всіма платформами і, здається, знаходиться у стані "ЕКСПЕРИМЕНТАЛЬНО" за допомогою кутових документів


2
Це не працює для мене. Я виявив, що window.location.search включає провідний знак питання параметрів рядків запитів. Отже, ключ першого параметра матиме знак запитання.
AJ Morris

AJ Morris, щоб обійти ваше питання: if (window.location.search.indexOf('?') == 0){ normalizedQueryString = window.location.search.substring(1); } else { normalizedQueryString = window.location.search; } let params = new URLSearchParams(normalizedQueryString);
amidexterous

URLSearchParams його застаріло. Тепер ви можете це зробити за допомогою ActivateRoute.
Роберт Бласко Вільярроя

7

По-перше, те, що я виявив, що працює з Angular2, - це те, що URL-адреса з рядком запиту буде /path;query=value1

Для доступу до нього в компоненті ви використовуєте Так є, але тепер слід блок-код:

    constructor(params: RouteParams){
    var val = params.get("query");
    }

Щодо того, чому він буде видалений при завантаженні компонента, це не поведінка за замовчуванням. Я конкретно перевірив чистий тестовий проект і не був перенаправлений чи змінений. Це маршрут за замовчуванням або щось інше, що особливе щодо маршрутизації?

Читайте про маршрутизацію з рядками запитів та парами у навчальному посібнику Angular2 за посиланням https://angular.io/docs/ts/latest/guide/router.html#!#query-parameters


Я не можу використовувати парами типу "; param1 = value1; param2 = value2", це посилання, створене на іншому сайті та переспрямоване на моєму веб-сайті типу "example.com/auth?code_for_auth=askjfbkajdsbfksajdf"
FireGM

Наразі, як маршрутизація налаштована в Angular2 на даний момент, я не думаю, що це реально можливо. Якийсь спосіб вирішення знадобиться, оскільки маршрутизація дитини залежить від URL-адреси матриці. Щодо як мінімум я знаю. Я б перехопив це на своєму веб-сервері і перетворив їх на хак, смокче, але наразі не можу придумати іншого шляху
Намірна

У вас немає можливості попросити сайт, що посилається, змінити їх URL?
Намірна

1
Ні. Але я вирішив проблему просто вручну проаналізувати Location.path ()
FireGM

4
це рішення застаріле!

7

Ви можете отримати параметри запиту при передачі в URL за допомогою ActivateRoute, як зазначено нижче: -

URL: - http: /domain.com? test = abc

import { Component } from '@angular/core';
import { ActivatedRoute }     from '@angular/router';

@Component({
  selector: 'my-home'
})
export class HomeComponent {

  constructor(private sharedServices : SharedService,private route: ActivatedRoute) { 
    route.queryParams.subscribe(
      data => console.log('queryParams', data['test']));
  }

}

7

Отримайте URL-парам як об’єкт.

import { Router } from '@angular/router';
constructor(private router: Router) {
    console.log(router.parseUrl(router.url));
}

2

Якщо ви хочете отримати параметр запиту лише один раз, найкращим способом є використання методу take, тому вам не потрібно турбуватися про підписку. Ось простий фрагмент: -

constructor(private route: ActivatedRoute) {
  route.snapshot.queryParamMap.take(1).subscribe(params => {
     let category = params.get('category')
     console.log(category);
  })
}

Примітка: Видаліть take (1), якщо ви хочете використовувати значення параметрів у майбутньому.


2

тепер це:

this.activatedRoute.queryParams.subscribe((params: Params) => {
  console.log(params);
});

1
Дякуємо за цей фрагмент коду, який може надати деяку короткочасну допомогу. Правильне пояснення значно покращило б його довгострокове значення, показавши, чому це хороше рішення проблеми та зробило б кориснішим майбутнім читачам інші подібні питання. Будь ласка, відредагуйте свою відповідь, щоб додати пояснення, включаючи припущення, які ви зробили
Шон К.

1

Сподіваюся, це допоможе комусь іншому.

Питання вище зазначає, що значення параметри запиту потрібно після перенаправлення сторінки, і ми можемо припустити, що значення знімка (альтернатива, що не спостерігається) буде достатньою.

Тут ніхто не згадував про snapshot.paramMap.get з офіційної документації .

this.route.snapshot.paramMap.get('id')

Отже, перш ніж надсилати його, додайте це в компонент для надсилання / перенаправлення:

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

потім повторно направляйте як (задокументовано тут ):

this.router.navigate(['/heroes', { id: heroId, foo: 'foo' }]);

або просто:

this.router.navigate(['/heroes', heroId ]);

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

 { path: 'hero/:id', component: HeroDetailComponent }

І нарешті, у вашому компоненті, який повинен використовувати параметр запиту

  • додайте імпорт ( тут задокументовано ):

    import { Router, ActivatedRoute, ParamMap } from '@angular/router';
  • введіть ActivateRoute

(Документація також імпортує SwitchMap, а також вводить маршрутизатор та HeroService - але вони потрібні лише для спостережуваної альтернативи - вони НЕ потрібні, коли ви використовуєте альтернативу знімків, як у нашому випадку):

    constructor(
      private route: ActivatedRoute
    ) {}
  • і отримаєте потрібне вам значення (задокументовано тут ):

    ngOnInit() {
      const id = this.route.snapshot.paramMap.get('id');
    }

ПРИМІТКА: ЯКЩО ВИ ДОДАТИМ РЕКУЛЮЦІЙНИЙ МОДУЛЬ ДО МОДУЛЯ ДІЯЛЬНОСТІ (ЯК ПОКАЗАНО В ДОКУМЕНТАЦІЇ), ЗАБЕЗПЕЧЕННЯ В УПРАВЛІННІ ДОПОМОГИ. ТАКИЙ МОДУЛЬ РОТУВАННЯ ПОЧАТИ ДО ПЕРЕД AppRoutingModule (або іншого файлу з маршрутами програми для кореневого рівня) В ІМПОРТІ: []. ДРУГІ ХАРАКТЕРИСТИКИ ДІЯЛЬНОСТІ НЕ ЗНАЙДУТЬСЯ (ЯКЩО БУДУТЬ ПІСЛЯ {шлях: "**", перенаправляємо до: "/ не знайдено"}, і ви побачите лише не знайдене повідомлення).


1

Вам просто потрібно ввести ActivateRoute в конструктор, а потім просто отримати доступ до нього парам або queryParams

constructor(private route:ActivatedRoute){}
ngOnInit(){
        this.route.queryParams.subscribe(params=>{
        let username=params['username'];
      });
 }

У деяких випадках він не дає нічого в NgOnInit ... можливо, через виклик init перед ініціалізацією парам в цьому випадку ви можете цього досягти, попросивши спостерігачів почекати деякий час за функцією debounceTime (1000)

наприклад =>

 constructor(private route:ActivatedRoute){}
    ngOnInit(){
            this.route.queryParams.debounceTime(100).subscribe(params=>{
            let username=params['username'];
          });
     }

debounceTime () Подає значення з джерела, яке можна спостерігати лише після того, як пройшов певний проміжок часу без іншого викиду джерела


0

Ви не можете отримати параметр від RouterState, якщо він не визначений у маршруті, тому у вашому прикладі ви повинні проаналізувати рядок запитів ...

Ось код, який я використав:

let re = /[?&]([^=#&]+)=([^&#]*)/g;
let match;
let isMatch = true;
let matches = [];
while (isMatch) {
    match = re.exec(window.location.href);
    if (match !== null) {
        matches[decodeURIComponent(match[1])] = decodeURIComponent(match[2]);
        if (match.index === re.lastIndex) {
            re.lastIndex++;
        }
    }
    else {
        isMatch = false;
    }
}
console.log(matches);


0

Запит та шлях (кутова 8)

Якщо у вас є URL на зразок https://myapp.com/owner/123/show?height=23, тоді використовуйте

combineLatest( [this.route.paramMap, this.route.queryParamMap] )
  .subscribe( ([pathParams, queryParams]) => {
    let ownerId = pathParams.get('ownerId');    // =123
    let height  = queryParams.get('height');    // =height
    // ...
  })

ОНОВЛЕННЯ

Якщо ви використовуєте this.router.navigate([yourUrl]);і ваші параметри запиту вбудовуються в yourUrlрядок, кутовий кодує URL-адресу, і ви отримуєте щось подібне https://myapp.com/owner/123/show%3Fheight%323 - і вище рішення дасть неправильний результат ( queryParams буде порожнім, а параметри запитів можна буде приклеїти до останнього параму шляху, якщо він знаходиться в кінці шляху). У цьому випадку змініть спосіб навігації на цей

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