Come ottenere parametri di query dall'URL in Angular 2?


237

Uso angular2.0.0-beta.7. Quando un componente viene caricato su un percorso come /path?query=value1viene reindirizzato /path. Perché sono stati rimossi i parametri GET? Come posso conservare i parametri?

Ho un errore nei router. Se ho un percorso principale come

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

e il mio percorso bambino come

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

quindi non riesco a ottenere parametri in TodoListComponent. Sono in grado di ottenere

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

ma voglio il classico

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

1
come hai specificato @RouteConfigper questo path?
Pankaj Parkar,

Ho trovato un errore Ho percorso principale e percorso figlio e se ho percorso principale come {percorso: '/ todos / ...', nome: 'TodoMain', componente: TodoMainComponent} e percorso figlio {percorso: '/', componente: TodoListComponent, name: 'TodoList', useAsDefault: true}, non funziona e reindirizza per url senza parametri di query.
FireGM,

Risposte:


412

Iniettando un'istanza di ActivatedRouteuno è possibile abbonarsi a una varietà di osservabili, tra cui a queryParamse paramsosservabili:

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);
      });
  }

}

UNA NOTA RELATIVA ALLA CANCELLAZIONE DELLA REGISTRAZIONE

@Reto e @ codef0rmer avevano giustamente sottolineato che, in base ai documenti ufficiali, in questo caso non è necessario un metodo unsubscribe()interno ai componenti onDestroy(). Questo è stato rimosso dal mio esempio di codice. (vedi la casella di avviso blu in questo tutorial)


2
Suggerisco inoltre di sostituire l'abbonamento con una promessa - in questo caso speciale. this.activatedRoute.params.toPromise () .then (response => ...) .catch (error => ...);
dic

Dove posso passare "attivatoRoute"?
Michali,

20
Dalla documentazione ufficiale: devo annullare l'iscrizione? 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.
Reto,

reindirizzamenti angolari senza attivare l'abbonamento (o la promessa). Posso vedere l'originale callback con il token, ma poi reindirizza al percorso senza la query params e console.log (param) è solo un oggetto vuoto.
FlavorScape

1
@Sobhan, sì, c'è una differenza. L'operatore switchMap restituisce un osservabile mentre l'operatore di sottoscrizione consente all'osservatore (il nostro componente) di vedere gli articoli che alla fine vengono emessi da un osservabile. Quindi nei documenti ci sono 2 istanze di switchmap utilizzate. 1) Hanno usato switchMap per aggiungere una richiesta per eroi. SwitchMap, diversamente dall'abbonamento, assicurerà che la richiesta venga annullata nel caso in cui l'utente ritorni sulla rotta mentre recupera un eroe. 2) Viene utilizzato un tubo asincrono. Le pipe asincrone consumano un osservabile, quindi non è necessario iscriversi (la pipe asincrona lo farà per te).
Stephen Paul,

103

Quando un URL come questo http://stackoverflow.com?param1=value

È possibile ottenere il parametro 1 tramite il codice seguente:

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
significa che non è più necessario aggiungere "/: id" nel percorso di routeconfig? perché ottengo "indefinito" quando lo uso, quindi devo ancora avere un errore da qualche parte
Axelle,

2
Grande. Questo lo cercavo perché ho bisogno di leggere i parametri direttamente dall'URL di un server dinamico. Non riesco a usare la navigazione.
The.Bear,

37

Anche se la domanda specifica la versione beta 7 , questa domanda si presenta anche come principale risultato di ricerca su Google per frasi comuni come i parametri della query angolare 2 . Per questo motivo ecco una risposta per il router più recente (attualmente in alpha.7 ).

Il modo in cui i parametri vengono letti è cambiato radicalmente. Per prima cosa devi iniettare la dipendenza chiamata Routernei parametri del costruttore come:

constructor(private router: Router) { }

e successivamente possiamo sottoscrivere i parametri della query sul nostro ngOnInitmetodo (anche il costruttore va bene, ma ngOnInitdovrebbe essere usato per la testabilità) come

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

In questo esempio leggiamo l' ID parametro della query da URL like example.com?id=41.

Ci sono ancora alcune cose da notare:

  1. L'accesso alla proprietà di paramslike params['id']restituisce sempre una stringa e questo può essere convertito in numero prefissandolo con +.
  2. Il motivo per cui i parametri della query vengono recuperati con osservabile è che consente di riutilizzare la stessa istanza del componente anziché caricarne una nuova. Ogni volta che si modifica il parametro della query, si verificherà un nuovo evento a cui ci siamo abbonati e quindi possiamo reagire di conseguenza alle modifiche.

C'è un modo per avere più parametri che vanno allo stesso membro? Ad esempio, vorrei "id" o "identificazione" per accedere a this.selectedId.
phandinhlan,

@phandinhlan: Beh, non è proprio una domanda relativa ad Angular 2. Ovviamente può essere implementata, ma devi definire tu stesso la logica. Fondamentalmente quello che vuoi fare è controllare prima se la prima chiave è definita e solo dopo leggere il valore da essa, e in caso contrario, leggere il valore con un'altra chiave. Questo potrebbe essere ottenuto con qualcosa del genere if (params.hasOwnProperty('id')) { this.selectedId = params['id'] } else { this.selectedId = params['identification']}.
Roope Hakulinen,

Sì, ho finito per fare qualcosa del genere. Ho solo pensato che ci sarebbe stato un modo "integrato" come: this.selectedId = + params ['id']; this.selectedId = + params ['identificazione']; Ovviamente ciò non ha alcun senso e non funziona.
phandinhlan,

28

Mi è piaciuta molto la risposta di StevePaul, ma possiamo fare lo stesso senza abbonarsi / annullare l'iscrizione.

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
l'avvertimento ovviamente con questo è che sarà il valore iniziale e le successive modifiche non verranno riflesse. Quindi, se stai modificando i parametri URL a livello di codice come parte della tua logica è qualcosa di cui devi essere consapevole
ambidestro

Non sono sicuro se questo è cambiato con le versioni successive di Angular, ma ora lo vedo in this.activatedRoute.snapshot.queryParams
Michael

21

Per inviare parametri di query

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

Per ricevere parametri di query

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

Fonte ufficiale


La lettura funziona bene, ma fa distinzione tra maiuscole e minuscole. Come possiamo renderlo insensibile alle maiuscole?
Unnie il

12

Ciao, puoi usare URLSearchParams, puoi leggere di più qui .

importare:

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

e funzione:

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

Avviso : non è supportato da tutte le piattaforme e sembra essere nello stato "SPERIMENTALE" da documenti angolari


2
Questo non funziona per me. Ho scoperto che window.location.search include il punto interrogativo principale dei parametri di querystring. Quindi, la chiave per il primo parametro avrà il punto interrogativo anteposto.
AJ Morris,

AJ Morris, per aggirare il problema: if (window.location.search.indexOf('?') == 0){ normalizedQueryString = window.location.search.substring(1); } else { normalizedQueryString = window.location.search; } let params = new URLSearchParams(normalizedQueryString);
ambidestro

URLSearchParams è obsoleto. Ora puoi farlo con ActivatedRoute.
Robert Blasco Villarroya,

7

Prima di tutto, quello che ho trovato lavorando con Angular2 è che sarebbe l'URL con una stringa di query /path;query=value1

Per accedervi in ​​un componente che usi Così è, ma ora segue un blocco di codice:

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

Quanto al motivo per cui verrebbe rimosso quando si carica il componente, questo non è un comportamento predefinito. Ho controllato specificamente in un progetto di test pulito e non sono stato reindirizzato o modificato. È una route predefinita o qualcos'altro di speciale sull'instradamento?

Leggi informazioni sull'instradamento con stringhe di query e parametri nel Tutorial Angular2 all'indirizzo https://angular.io/docs/ts/latest/guide/router.html#!#query-parameters


Non posso usare parametri come "; param1 = valore1; param2 = valore2", questo link generato su un altro sito e reindirizza sul mio sito come "esempio.com/auth?code_for_auth=askjfbkajdsbfksajdf"
FireGM

Il modo in cui il routing è impostato in Angular2 al momento, non credo sia davvero possibile. Una sorta di soluzione alternativa sarà necessaria poiché il routing figlio dipende dall'URL matrice. Per quanto ne so almeno. Lo intercetterei sul mio server web e li trasformerei come un hack, fa schifo ma al momento non riesco a pensare ad un altro modo
Namirna,

Non hai la possibilità di chiedere al sito di collegamento di cambiare il loro URL?
Namirna,

1
No. Ma ho risolto il problema semplicemente analizzando manualmente Location.path ()
FireGM il

4
questa soluzione è diventata obsoleta!

7

È possibile ottenere i parametri della query quando vengono passati nell'URL utilizzando ActivatedRoute come indicato di seguito: -

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

Ottieni il parametro URL come oggetto.

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

2

Se desideri ottenere il parametro di query una sola volta, il modo migliore è utilizzare il metodo take in modo da non doverti preoccupare di annullare l'iscrizione. Ecco il semplice frammento: -

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

Nota: rimuovere take (1) se si desidera utilizzare i valori dei parametri in futuro.


2

ora è:

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

1
Grazie per questo frammento di codice, che potrebbe fornire un aiuto limitato a breve termine. Una spiegazione adeguata migliorerebbe notevolmente il suo valore a lungo termine mostrando perché questa è una buona soluzione al problema e la renderebbe più utile ai futuri lettori con altre domande simili. Modifica la tua risposta per aggiungere alcune spiegazioni, comprese le ipotesi che hai fatto
Shawn C.

1

Spero che possa aiutare qualcun altro.

La domanda sopra afferma che il valore del parametro della query è necessario dopo il reindirizzamento della pagina e possiamo supporre che il valore dell'istantanea (l'alternativa non osservabile) sia sufficiente.

Nessuno qui menzionato su snapshot.paramMap.get dalla documentazione ufficiale .

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

Quindi prima di inviarlo aggiungi questo nel componente di invio / reindirizzamento:

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

quindi reindirizzare come (documentato qui ):

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

o semplicemente:

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

Assicurati di averlo aggiunto nel modulo di routing come documentato qui :

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

E infine, nel componente che deve utilizzare la query param

  • aggiungi importazioni (documentato qui ):

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

(la documentazione importa anche switchMap e inietta anche Router ed HeroService - ma sono necessari solo per un'alternativa osservabile - NON sono necessari quando si utilizza un'alternativa di snapshot come nel nostro caso):

    constructor(
      private route: ActivatedRoute
    ) {}
  • e ottieni il valore che ti serve (documentato qui ):

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

NOTA: SE AGGIUNGI IL MODULO DI ROUTING A UN MODULO DI FUNZIONALITÀ (COME INDICATO NELLA DOCUMENTAZIONE) ASSICURATI CHE IN APP.MODULE.ts QUESTO MODULO DI ROUTING venga PRIMA DI AppRoutingModule (o altro file con percorsi di app di livello radice) IN IMPORTAZIONI: []. LE STRADE DELLE FUNZIONALITÀ ALTRE NON SARANNO TROVATE (COME AVREBBERO AVUTO DOPO {percorso: '**', reindirizzare a: '/ non trovato'} e vedresti solo il messaggio non trovato).


1

Devi solo iniettare ActivatedRoute nel costruttore e quindi accedere ai parametri o queryParams su di esso

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

In alcuni casi non dà nulla in NgOnInit ... forse a causa della chiamata di init prima dell'inizializzazione dei parametri in questo caso puoi farlo chiedendo a osservabile di attendere qualche tempo con la funzione debounceTime (1000)

es =>

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

debounceTime () Emette un valore dalla sorgente osservabile solo dopo un determinato intervallo di tempo trascorso senza un'altra emissione della sorgente


0

Non è possibile ottenere un parametro da RouterState se non è definito nella route, quindi nell'esempio è necessario analizzare la stringa di query ...

Ecco il codice che ho usato:

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

Query and Path (Angular 8)

Se hai un URL come https://myapp.com/owner/123/show?height=23, utilizza

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

AGGIORNARE

Nel caso in cui si utilizzi this.router.navigate([yourUrl]);e i parametri della query siano incorporati nella yourUrlstringa, angolare codifica un URL e si ottiene qualcosa del genere https://myapp.com/owner/123/show%3Fheight%323 - e la soluzione sopra genererà risultati errati ( queryParams sarà vuoto e i parametri della query possono essere incollati all'ultimo parametro del percorso se si trova alla fine del percorso). In questo caso cambia la modalità di navigazione in questo

this.router.navigateByUrl(yourUrl);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.