Como obter parâmetros de consulta do URL no Angular 5?

180

Estou usando o angular 5.0.3, gostaria de iniciar meu aplicativo com vários parâmetros de consulta como /app?param1=hallo&param2=123. Todas as dicas fornecidas em Como obter parâmetros de consulta a partir do URL no Angular 2? Nao funciona para mim.

Alguma idéia de como os parâmetros de consulta funcionam?

private getQueryParameter(key: string): string {
  const parameters = new URLSearchParams(window.location.search);
  return parameters.get(key);
}

Essa função privada me ajuda a obter meus parâmetros, mas não acho que seja o caminho certo no novo ambiente Angular.

[update:] Meu aplicativo principal parece

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

  constructor(private route: ActivatedRoute) {}

  ngOnInit(): void {
    // would like to get query parameters here...
    // this.route...
  }
}
Lars
fonte
Você está usando roteadores? De onde vem o URL?
Vinod Bhavnani
Sim, tenha um ActivatedRoute. Atualizei minha pergunta para mostrar como é meu componente principal.
Lars
Você também pode me mostrar sua rota constante, onde você configurou todas as rotas?
Vinod Bhavnani
const appRoutes: Routes = [{path: "one", componente: PageOneComponent}, {path: "", redirectTo: "/ one", pathMatch: "full"}, {path: "**", redirectTo: "/ 1"} ]; Minha rota constante. Gostaria de obter todos os parâmetros na loja de aplicativos principal em um DTO e depois navegar para outra página. A navegação da página funciona conforme o esperado, mas eu recebo os parâmetros de consulta principalmente pela minha função 'getQueryParameter'. Percebo na sua pergunta que existe algo que esqueci. Preciso marcar meus nomes de parâmetro em algum lugar?
Lars
Sim, em suas rotas, você precisa definir os parâmetros também. Se você verificar os documentos de roteamento em angular.io, poderá ver como eles definem parâmetros em uma rota específica. Algo parecido com isto {path: 'abc /: param1', component: componentClassName}
Vinod Bhavnani

Respostas:

237

No Angular 5, os parâmetros de consulta são acessados ​​assinando this.route.queryParams.

Exemplo: /app?param1=hallo&param2=123

param1: string;
param2: string;
constructor(private route: ActivatedRoute) {
    console.log('Called Constructor');
    this.route.queryParams.subscribe(params => {
        this.param1 = params['param1'];
        this.param2 = params['param2'];
    });
}

enquanto que as variáveis ​​de caminho são acessadas por this.route.snapshot.params

Exemplo: /param1/:param1/param2/:param2

param1: string;
param2: string;
constructor(private route: ActivatedRoute) {
    this.param1 = this.route.snapshot.params.param1;
    this.param2 = this.route.snapshot.params.param2;
}
Vijayendra Mudigal
fonte
15
De acordo com os documentos do Angular 6 , o uso de ActivatedRoute.queryParams e .params é desencorajado e pode ser preterido em versões futuras; Veja a atualização aqui
grreeenn
1
@ShubhenduVaid explica por que eles deveriam usar o ngOnInit em vez do construtor. A melhor prática estará usando RxJS observável, em seguida, usar abordagem declarativa quando se trabalha com observáveis, em seguida, usando async no html
coderpatomx
118

Esta é a solução mais limpa para mim

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

export class MyComponent {
  constructor(
    private route: ActivatedRoute
  ) {}

  ngOnInit() {
    const firstParam: string = this.route.snapshot.queryParamMap.get('firstParamKey');
    const secondParam: string = this.route.snapshot.queryParamMap.get('secondParamKey');
  }
}
dapperdan1985
fonte
Isso é útil, obrigado. No angular 6.0.8, estou usando isso e funciona para mim: this.route.snapshot.queryParams ["firstParamKey"]
fluidguid
2
Isso funciona para mim no Angular8. this.route.snapshot.queryParamMap funciona. this.route.snapshot.paramMap não funciona para mim.
Romeo Profijt em 18/02
89

Eu sei que o OP pediu a solução Angular 5, mas ainda assim para todos vocês que se deparam com essa pergunta em versões Angular mais novas (6+). Citando os Documentos , sobre ActivatedRoute.queryParams (em que a maioria das outras respostas se baseia):

Duas propriedades mais antigas ainda estão disponíveis. Eles são menos capazes que suas substituições, desencorajados e podem ser preteridos em uma versão futura do Angular.

params - um Observable que contém os parâmetros obrigatórios e opcionais específicos para a rota. Use o paramMap.

queryParams - um Observable que contém os parâmetros de consulta disponíveis para todas as rotas. Use queryParamMap.

De acordo com o Documentos , a maneira simples de obter os parâmetros de consulta seria assim:

constructor(private route: ActivatedRoute) { }

ngOnInit() {
    this.param1 = this.route.snapshot.paramMap.get('param1');
    this.param2 = this.route.snapshot.paramMap.get('param2');
}

Para formas mais avançadas (por exemplo, reutilização avançada de componentes), consulte este capítulo do Documentos.

EDITAR:

Como indicado corretamente nos comentários abaixo, esta resposta está errada - pelo menos no caso especificado pelo OP.

O OP pede para obter parâmetros globais de consulta (/ app? Param1 = hallo & param2 = 123); Nesse caso, você deve usar queryParamMap (assim como na resposta dapperdan1985).

O paramMap, por outro lado, é usado em parâmetros específicos da rota (por exemplo, / app /: param1 /: param2, resultando em / app / hallo / 123).

Obrigado a @JasonRoyle e @daka por apontar isso.

Grreeenn
fonte
10
Isso não deveria estar sendo usado para queryParamMapnão paramMapbuscar parâmetros da string de consulta?
Jason Royle
2
@JasonRoyle Parece que você está correto, paramMapnão funciona.
daka
1
Esta resposta precisa ser corrigida conforme os comentários acima.
daka
@ JasonRoyle, daka, você está certo, obrigado por apontar. Corrigida a resposta.
grreeenn
Encontrado código perfeito de trabalho: jsonworld.com/blog/...
Soni Kumari
17

Você também pode usar HttpParams , como:

  getParamValueQueryString( paramName ) {
    const url = window.location.href;
    let paramValue;
    if (url.includes('?')) {
      const httpParams = new HttpParams({ fromString: url.split('?')[1] });
      paramValue = httpParams.get(paramName);
    }
    return paramValue;
  }
a5tr0
fonte
1
Apenas esclarecer, eu tenho dois domínios apontam para site de idioma diferente. localhost / -> Por exemplo, localhost /? lang = fr -> francês. E eu tenho de roteamento: path: '', redirectTo: '/list' . O this.route.snapshot não funciona para mim porque redirecionaTo / list que elimina a queryString 'lang'. Mas esta solução funciona para mim.
Ryan Huang
Como @RyanHuang, eu tenho o mesmo problema. Mas essa solução funcionou no meu primeiro teste.
Gi1ber7 11/11/19
Encontrar uma melhor solução do que acima: jsonworld.com/blog/...
Soni Kumari
11
import { ParamMap, Router, ActivatedRoute } from '@angular/router';

constructor(private route: ActivatedRoute) {}

ngOnInit() {
    console.log(this.route.snapshot.queryParamMap);
}

ATUALIZAR

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

export class LoginComponent {
    constructor(private router: Router) {
        const snapshot: RouterStateSnapshot = router.routerState.snapshot;
        console.log(snapshot);  // <-- hope it helps
    }
}
Dmitry Grinko
fonte
6
isso parece não ser suficiente, recebo o ActivatedRouteSnapshot, mas queryParams é um objeto vazio, os parâmetros também estão vazios e .queryParamMap.get ('name') retorna nulo. Parece que ngOnInit () é muito cedo para obter esses parâmetros de consulta.
Lars
na verdade, se você deseja obter esses parâmetros, deve alterar sua rota.
Dmitry Grinko
Eu tenho cerca de 10 parâmetros em ordem diferente. Portanto, devo usar parâmetros de consulta nomeados. E como eu configuro meu AppComponent principal para perceber que existem 10 parâmetros. url / myprogram? a = 1 & b = 2 & c = 4 ... parece que estou com um problema? Preciso rotear todos os parâmetros para outro componente? Espero que não.
Lars
Você tentou este? this.route.snapshot.queryParamMap
Dmitry Grinko
1
O @DmitryGrinko colocar um ID de entidade em uma rota não é um padrão ruim, pois permite um link profundo para uma visualização de detalhes.
Karl
4

Deparei com essa questão quando procurava uma solução semelhante, mas não precisava de nada como roteamento completo no nível do aplicativo ou mais módulos importados.

O código a seguir funciona muito bem para o meu uso e não requer módulos ou importações adicionais.

  GetParam(name){
    const results = new RegExp('[\\?&]' + name + '=([^&#]*)').exec(window.location.href);
    if(!results){
      return 0;
    }
    return results[1] || 0;
  }

  PrintParams() {
    console.log('param1 = ' + this.GetParam('param1'));
    console.log('param2 = ' + this.GetParam('param2'));
  }

http://localhost:4200/?param1=hello&param2=123 saídas:

param1 = hello
param2 = 123
Reed
fonte
4

Parâmetros de consulta e caminho (Angular 8)

Para URL como https://myapp.com/user/666/read?age=23, use

import { combineLatest } from 'rxjs';
// ...

combineLatest( [this.route.paramMap, this.route.queryParamMap] )
  .subscribe( ([pathParams, queryParams]) => {
    let userId = pathParams.get('userId');    // =666
    let age    = queryParams.get('age');      // =23
    // ...
  })

ATUALIZAR

Caso você use this.router.navigate([someUrl]);e seus parâmetros de consulta sejam incorporados à someUrlstring, o angular codifica uma URL e você obtém algo como https://myapp.com/user/666/read%3Fage%323 - e a solução acima dará um resultado errado ( queryParams estará vazio e os parâmetros do caminho podem ser colados no último parâmetro do caminho, se estiver no final do caminho). Nesse caso, altere o modo de navegação para este

this.router.navigateByUrl(someUrl);
Kamil Kiełczewski
fonte
1
Obrigado @Kamil Kiełczewski, você salva meu dia
Tan Nguyen
2

Infelizmente, a solução mais limpa não é a solução mais extensível. Nas versões recentes do Angular, é sugerido nas outras respostas que você pode facilmente obter os parâmetros de consulta usando o ActivatedRoute Injectible e utilizando especificamente a propriedade snapshot:

this.route.snapshot.queryParamMap.get('param')

ou a propriedade subscrever (usada nos casos em que a string de consulta será atualizada, por exemplo, navegando pelos IDs do usuário):

this.route.queryParamMap.subscribe(params => console.log(params));

Estou aqui para dizer que essas soluções têm uma falha que não foi resolvida há algum tempo: https://github.com/angular/angular/issues/12157

Em suma, a única solução à prova de balas é usar o bom e velho javascript de baunilha. Nesse caso, criei um serviço para manipulação de URL:

import { Injectable } from '@angular/core';
import { IUrl } from './iurl';

@Injectable()
export class UrlService {
    static parseQuery(url: string): IUrl {
        const query = url.slice(url.indexOf('?')+1).split('&').reduce( (acc,query) => {
            const parts = query.split('=');
            acc[parts[0]] = parts[1];
            return acc;
        }, {});

        return {
            a: query['a'],
            b: query['b'],
            c: query['c'],
            d: query['d'],
            e: query['e']
        }
    }
}
Donato
fonte
2

O Angular Router fornece o método parseUrl (url: string) que analisa o URL no UrlTree . Uma das propriedades do UrlTree é queryParams. Então você pode fazer algo como:

this.router.parseUrl(this.router.url).queryParams[key] || '';
Adam Michalak
fonte
Não poste várias respostas idênticas para perguntas diferentes. Há alguns conselhos úteis sobre essa prática aqui
David Buck
Use isso se você não precisar lidar com alterações de URL, ou seja, os parâmetros já estão disponíveis no URL atual. Faça da maneira observável de outra maneira.
tom
1

Quando você tem um objeto de rota vazio, isso se deve principalmente ao fato de você não estar usando uma tomada do roteador no app.component.html.

Sem isso, você não poderá obter um objeto de rota significativo com subObjects não vazios, particularmente params e queryParams.

Tente adicionar um <router-outlet><router-outlet>pouco antes de ligar para o seu <app-main-component></app-main-component>

Antes disso, verifique se você tem seus parâmetros de consulta prontos no roteamento de aplicativos> que exportam a classe Route usada pelo componente App:

param: '/param/:dynamicParam', path: MyMainComponent

Última coisa, é claro, para obter seus parâmetros, eu this.route.snapshot.params.dynamicParampessoalmente uso em que dynamicParam é o nome usado no componente de roteamento de aplicativos :)

andrea06590
fonte
1

Tenha cuidado com suas rotas. Um "redirectTo" removerá | descarte qualquer parâmetro de consulta.

const appRoutes: Routes [
 {path: "one", component: PageOneComponent},
 {path: "two", component: PageTwoComponent},
 {path: "", redirectTo: "/one", pathMatch: full},
 {path: "**", redirectTo: "/two"}
]

Chamei meu componente principal com parâmetros de consulta como "/ main? Param1 = a & param2 = b e presumo que meus parâmetros de consulta cheguem ao método" ngOnInit () "no componente principal antes que o redirecionamento de redirecionamento tenha efeito.

Mas isso está errado. O redirecionamento veio antes, elimine os parâmetros de consulta e chame o método ngOnInit () no componente principal sem parâmetros de consulta.

Alterei a terceira linha das minhas rotas para

{path: "", component: PageOneComponent},

e agora meus parâmetros de consulta estão acessíveis nos principais componentes ngOnInit e também no PageOneComponent.

Lars
fonte
1

Encontrado em: Componentes pai fica Params vazio do ActivatedRoute

Trabalhou para mim:

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

@Component({
  selector: 'app-navigation-bar',
  templateUrl: './navigation-bar.component.html',
  styleUrls: ['./navigation-bar.component.scss']
})
export class NavigationBarComponent implements OnInit, OnDestroy {
  private sub: any;
  constructor(private route: ActivatedRoute, private router: Router) {}

  ngOnInit() {
    this.sub = this.router.events.subscribe(val => {
      if (val instanceof RoutesRecognized) {
        console.log(val.state.root.firstChild.params);
      }
    });
  }

  ngOnDestroy() {
    this.sub.unsubscribe();
  }

}
Yonatan Ayalon
fonte
0

Acabei de encontrar o mesmo problema e a maioria das respostas aqui parece resolvê-lo apenas para o roteamento interno Angular e, em seguida, algumas delas para parâmetros de rota que não são iguais aos parâmetros de solicitação.

Acho que tenho um caso de uso semelhante à pergunta original de Lars.

Para mim, o caso de uso é, por exemplo, rastreamento de referência:

Angular em execução mycoolpage.com, com roteamento de hash, então mycoolpage.comredireciona para mycoolpage.com/#/. Para referência, no entanto, um link como mycoolpage.com?referrer=footambém deve ser utilizável. Infelizmente, o Angular retira imediatamente os parâmetros de solicitação, indo diretamente para mycoolpage.com/#/.

Qualquer tipo de 'truque' ao usar um componente vazio + AuthGuard e obter queryParamsou queryParamMapnão, infelizmente, não funcionou para mim. Eles estavam sempre vazios.

Minha solução hacky acabou sendo lidar com isso em um pequeno script no index.htmlqual obtém a URL completa, com parâmetros de solicitação. Em seguida, pego o valor do parâmetro de solicitação por meio de manipulação de string e o defino no objeto window. Um serviço separado lida com a obtenção do ID do objeto da janela.

script index.html

const paramIndex = window.location.href.indexOf('referrer=');
if (!window.myRef && paramIndex > 0) {
  let param = window.location.href.substring(paramIndex);
  param = param.split('&')[0];
  param = param.substr(param.indexOf('=')+1);
  window.myRef = param;
}

Serviço

declare var window: any;

@Injectable()
export class ReferrerService {

  getReferrerId() {
    if (window.myRef) {
      return window.myRef;
    }
    return null;
  }
}
seBaka28
fonte
0

Solução Simples

 // in routing file
       {
            path: 'checkout/:cartId/:addressId',
            loadChildren: () => import('./pages/checkout/checkout.module').then(m => m.CheckoutPageModule)
          },

    // in Component file

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

                 constructor(
                      private _Router: ActivatedRoute
                  ) { }

                  ngOnInit() {
                    this.cartId = this._Router.snapshot.params.cartId;
                    this.addressId = this._Router.snapshot.params.addressId;
                    console.log(this.addressId, "addressId")
                    console.log(this.cartId, "cartId")
                  }
Shashwat Gupta
fonte
0

http: // localhost: 4200 / products? order = popular

Podemos acessar o parâmetro de consulta de pedidos como este:

this.route.queryParams
      .filter(params => params.order)
      .subscribe(params => {
        console.log(params)// {order: "popular"}

        this.order = params.order;
        console.log(this.order); // popular
      });
  }

Há também queryParamMap, que retorna um observável com um objeto paramMap.

Dado o seguinte URL de rota:

http: // localhost: 4200 / products? order = popular & filter = new

this.route.queryParamMap.subscribe(params => {
  this.orderObj = {...params.keys, ...params};
});

Fonte - https://alligator.io/angular/query-parameters/

San Jaisy
fonte
0

No, acho que o Angular 8:

ActivatedRoute.paramsfoi substituído por ActivatedRoute.paramMap ActivatedRoute.queryParamsfoi substituído por ActivatedRoute.queryParamMap

Marvin
fonte
-1
/*
Example below url with two param (type and name) 
URL : http://localhost:4200/updatePolicy?type=Medicare%20Insurance&name=FutrueInsurance
*/ 
  constructor(private route: ActivatedRoute) {
    //Read url query parameter `enter code here`
  this.route.queryParams.subscribe(params => {
    this.name= params['type'];
    this.type= params['name'];
    alert(this.type);
    alert(this.name);

 });

  }
Kaji Islam
fonte
-9

Se você não estiver usando o roteador Angular, tente, querystring . Instale-o

npm install --save querystring

ao seu projeto. No seu componente, faça algo parecido com isto

import * as qs from 'querystring';
...
ngOnInit() {
   const params = qs.parse(window.location.search.substring(1));
   ...
}

O substring(1)é necessário, porque se você tiver algo parecido com isto '/mypage?foo=bar', o nome da chave será?foo

Chuk Lee
fonte