Как получить параметры запроса от 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")
FireGM
источник
1
как вы указали @RouteConfigдля этого path?
Панкадж Паркар
Я нашел ошибку. У меня есть основной маршрут и дочерний маршрут, и если у меня есть основной маршрут, такой как {путь: '/ todos / ...', имя: 'TodoMain', компонент: TodoMainComponent} и дочерний маршрут {путь: '/', компонент: TodoListComponent, name: 'TodoList', useAsDefault: true}, это не работает и перенаправляет на URL без параметров запроса.
FireGM

Ответы:

413

Инъекцией экземпляра ActivatedRouteможно подписаться на различные наблюдаемые, включая a queryParamsи paramsobservable:

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.activationRoute.params.toPromise () .then (response => ...) .catch (error => ...);
Декабрь
Где я могу пройти «activRoute»?
Мичали
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
@ Собан, да, есть разница. Оператор switchMap возвращает Observable, в то время как оператор подписки позволяет наблюдателю (нашему компоненту) видеть элементы, в конечном итоге излучаемые Observable. Таким образом, в документах есть 2 случая использования карты переключения. 1) Они использовали switchMap, чтобы добавить запрос для героев. SwitchMap, в отличие от подписки, гарантирует, что запрос будет отменен, если пользователь повторно перейдет к маршруту, все еще находя героя. 2) Используется асинхронная труба. Асинхронные каналы потребляют наблюдаемое, поэтому подписываться на них не нужно (асинхронный канал сделает это за вас).
Стивен Пол
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? потому что я получаю "undefined", когда я использую это, поэтому у меня все еще должна быть ошибка где-то
Axelle
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. Доступ к свойству paramslike params['id']всегда возвращает строку , и ее можно преобразовать в число , поставив перед ним префикс +.
  2. Причина, по которой параметры запроса выбираются с помощью observable, заключается в том, что он позволяет повторно использовать один и тот же экземпляр компонента вместо загрузки нового. Каждый раз, когда изменяется параметр запроса, он вызывает новое событие, на которое мы подписались, и, таким образом, мы можем соответствующим образом реагировать на изменения.
Руп Хакулинен
источник
Есть ли способ иметь несколько параметров, идущих к одному члену? Например, я бы хотел, чтобы 'id' или 'идентификация' перешли на this.selectedId.
Phandinhlan
@phandinhlan: На самом деле это не вопрос, связанный с Angular 2. Конечно, он может быть реализован, но вам нужно определить логику самостоятельно. По сути, вы хотите сначала проверить, определен ли первый ключ, и только затем прочитать значение из него, а если нет, прочитать значение с другим ключом. Это может быть достигнуто с чем-то вроде if (params.hasOwnProperty('id')) { this.selectedId = params['id'] } else { this.selectedId = params['identification']}.
Руп Хакулинен
Да, в итоге я сделал что-то подобное. Я просто подумал, что будет какой-то «встроенный» способ, например: 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
}
codef0rmer
источник
7
оговорка, конечно, с этим, что это будет начальное значение, и последующие изменения не будут отражены. Так что, если вы изменяете параметры URL программно как часть вашей логики, то , что вам нужно , чтобы быть в курсе
двуличный
Не уверен, что это изменилось в более поздних версиях Angular, но теперь я вижу это в this.activationRoute.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'];
});

Официальный источник

dddenis
источник
Чтение работает отлично. Но оно чувствительно к регистру. Как мы можем сделать это без учета регистра?
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 Моррис
AJ Моррис, чтобы обойти проблему: if (window.location.search.indexOf('?') == 0){ normalizedQueryString = window.location.search.substring(1); } else { normalizedQueryString = window.location.search; } let params = new URLSearchParams(normalizedQueryString);
двуличный
URLSearchParams устарела. Теперь вы можете сделать это с помощью ActivatedRoute.
Роберт Бласко Вильярройя
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.

Namirna
источник
Я не могу использовать такие параметры, как «; param1 = значение1; param2 = значение2», эта ссылка создается на другом сайте и перенаправляет на мой сайт как «example.com/auth?code_for_auth=askjfbkajdsbfksajdf»
FireGM
То, как в настоящий момент настроена маршрутизация в Angular2, я не думаю, что это действительно возможно. Требуется какой-то обходной путь, поскольку дочерняя маршрутизация зависит от матрицы URL. Насколько я знаю по крайней мере. Я перехватил бы это на своем веб-сервере и преобразовал бы их как хак, отстой, но я не могу думать о другом пути в настоящее время
Намирна
У вас нет возможности попросить сайт ссылки изменить их URL?
Намирна
1
Но я решил эту проблему, просто вручную проанализировав Location.path ()
FireGM
4
это решение не рекомендуется!
7

Вы можете получить параметры запроса при передаче в URL, используя ActivatedRoute, как указано ниже: -

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));
}
Jsonras
источник
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';
  • ввести ActivatedRoute

(документация также импортирует switchMap, а также внедряет Router и HeroService - но они нужны только для наблюдаемой альтернативы - они НЕ нужны, когда вы используете альтернативный снимок, как в нашем случае):

    constructor(
      private route: ActivatedRoute
    ) {}
  • и получите нужное вам значение (задокументировано здесь ):

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

ПРИМЕЧАНИЕ. ЕСЛИ ВЫ ДОБАВЛЯЕТЕ МОДУЛЬ МАРШРУТИЗАЦИИ В МОДУЛЬ ОСОБЕННОСТИ (КАК ПОКАЗАНО В ДОКУМЕНТАЦИИ), УБЕДИТЕСЬ, ЧТО В APP.MODULE.ts ЭТО МОДУЛЬ МАРШРУТА ПРОХОДИТ ПЕРЕД AppRoutingModule (или другим файлом с маршрутами приложения корневого уровня) В ИМПОРТАХ: []. ПРОЧИЕ МАРШРУТЫ ОСОБЕННОСТИ НЕ НАЙДЕНЫ (ПОЭТОМУ ОНИ БУДУТ ПОСЛЕ {path: '**', redirectTo: '/ not-found'}, и вы увидите только не найденное сообщение).

Ула
источник
1

Вам просто нужно вставить ActivatedRoute в конструктор, а затем просто получить доступ к params или 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

Запрос и путь (Angular 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строку, то angular кодирует URL, и вы получаете что-то вроде этого https://myapp.com/owner/123/show%3Fheight%323 - и выше решение даст неправильный результат ( queryParams будет пустым, и параметры запроса могут быть приклеены к последнему параметру пути, если он находится в конце пути). В этом случае измените способ навигации на этот

this.router.navigateByUrl(yourUrl);
Камил Келчевски
источник