Wie bekomme ich Abfrageparameter von der URL in Angular 2?

236

Ich benutze angle2.0.0-beta.7. Wenn eine Komponente in einen Pfad geladen wird, zu dem /path?query=value1sie umgeleitet wird /path. Warum wurden die GET-Parameter entfernt? Wie kann ich die Parameter beibehalten?

Ich habe einen Fehler in den Routern. Wenn ich eine Hauptroute habe wie

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

und mein Kind Route wie

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

dann kann ich keine Parameter in TodoListComponent bekommen. Ich kann bekommen

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

aber ich will den Klassiker

query params("/my/path?param1=value1&param2=value2")
FireGM
quelle
1
wie Sie angegeben @RouteConfigfür diese path?
Pankaj Parkar
Ich habe einen Fehler gefunden. Ich habe Hauptroute und untergeordnete Route und wenn ich eine Hauptroute wie {Pfad: '/ todos / ...', Name: 'TodoMain', Komponente: TodoMainComponent} und untergeordnete Route {Pfad: '/', Komponente: TodoListComponent, name: 'TodoList', useAsDefault: true}, es funktioniert nicht und leitet ohne Abfrageparameter zur URL um.
FireGM

Antworten:

411

Durch Injizieren einer Instanz von ActivatedRoutekann man eine Vielzahl von Observablen abonnieren, einschließlich a queryParamsund a 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);
      });
  }

}

A HINWEIS ZUR ABMELDUNG

@Reto und @ codef0rmer hatten zu Recht darauf hingewiesen, dass gemäß den offiziellen Dokumenten in diesem Fall eine Methode unsubscribe()innerhalb der Komponenten onDestroy()nicht erforderlich ist. Dies wurde aus meinem Codebeispiel entfernt. (siehe blaues Warnfeld in diesem Tutorial)

Stephen Paul
quelle
2
Ich schlage außerdem vor, das Abonnement durch ein Versprechen zu ersetzen - in diesem speziellen Fall. this.activatedRoute.params.toPromise () .then (response => ...) .catch (error => ...);
Dezember
Wo kann ich "enabledRoute" übergeben?
Michali
19
Aus der offiziellen Dokumentation: Muss ich mich abmelden? 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
Winkelumleitungen ohne Auslösen des Abonnements (oder Versprechens). Ich kann den ursprünglichen oAUth-Rückruf mit dem Token sehen, aber dann wird er ohne die Abfrageparameter zur Route umgeleitet, und console.log (param) ist nur ein leeres Objekt.
FlavorScape
1
@Sobhan, ja da gibt es einen Unterschied. Der switchMap-Operator gibt ein Observable zurück, während der subscribe-Operator dem Beobachter (unserer Komponente) ermöglicht, die Elemente zu sehen, die letztendlich von einem Observable ausgegeben werden. In den Dokumenten werden also zwei Instanzen der Switchmap verwendet. 1) Sie haben switchMap verwendet, um eine Anfrage für Helden anzuhängen. Im Gegensatz zu "Abonnieren" stellt SwitchMap sicher, dass die Anforderung abgebrochen wird, wenn der Benutzer erneut zur Route navigiert, während er noch einen Helden abruft. 2) Eine asynchrone Pipe wird verwendet. Async-Pipes verbrauchen ein Observable, daher darf man es nicht abonnieren (das Async-Pipe erledigt das für Sie).
Stephen Paul
103

Wenn eine URL wie diese http://stackoverflow.com?param1=value

Sie können den Parameter 1 per Code erhalten:

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"];
    }
}
Trung
quelle
2
Bedeutet dies, dass Sie die "/: id" nicht mehr im Pfad der Routenkonfiguration hinzufügen müssen? weil ich "undefiniert" werde, wenn ich dies benutze, muss ich immer noch irgendwo einen Fehler haben
Axelle
2
Toll. Ich habe danach gesucht, weil ich die Parameter direkt von einer dynamischen Server-URL lesen muss. Ich kann nicht navigieren.
The.Bear
37

Obwohl in der Frage die Version Beta 7 angegeben ist , wird diese Frage bei Google auch als Top-Suchergebnis für häufig verwendete Ausdrücke wie Winkel-2-Abfrageparameter angezeigt . Aus diesem Grund finden Sie hier eine Antwort für den neuesten Router (derzeit in Alpha.7) ).

Die Art und Weise, wie die Parameter gelesen werden, hat sich dramatisch geändert. Zuerst müssen Sie die Routerin Ihre Konstruktorparameter aufgerufene Abhängigkeit wie folgt einfügen:

constructor(private router: Router) { }

und danach können wir die Abfrageparameter auf unserer ngOnInitMethode abonnieren (Konstruktor ist auch in Ordnung, ngOnInitsollte aber für die Testbarkeit verwendet werden) wie

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

In diesem Beispiel lesen wir die Abfrageparameter- ID von URL wieexample.com?id=41 .

Es gibt noch wenige Dinge zu beachten:

  1. Der Zugriff auf die Eigenschaft paramslike gibt params['id']immer eine Zeichenfolge zurück , die durch Präfixieren in eine Zahl konvertiert werden kann +.
  2. Der Grund, warum die Abfrageparameter mit Observable abgerufen werden, besteht darin, dass dieselbe Komponenteninstanz wiederverwendet werden kann, anstatt eine neue zu laden. Jedes Mal, wenn der Abfrageparameter geändert wird, wird ein neues Ereignis ausgelöst, das wir abonniert haben, und wir können entsprechend auf Änderungen reagieren.
Roope Hakulinen
quelle
Gibt es eine Möglichkeit, mehrere Parameter an dasselbe Mitglied zu senden? Zum Beispiel möchte ich, dass entweder 'id' oder 'identity' zu this.selectedId wechselt.
Phandinhlan
@phandinhlan: Nun, das ist nicht wirklich eine Frage im Zusammenhang mit Angular 2. Es kann natürlich implementiert werden, aber Sie müssen die Logik selbst definieren. Grundsätzlich möchten Sie zunächst prüfen, ob der erste Schlüssel definiert ist, und erst dann den Wert daraus lesen. Wenn nicht, lesen Sie den Wert mit einem anderen Schlüssel. Dies könnte mit so etwas erreicht werden if (params.hasOwnProperty('id')) { this.selectedId = params['id'] } else { this.selectedId = params['identification']}.
Roope Hakulinen
Ja, am Ende habe ich so etwas gemacht. Ich dachte nur, es gäbe eine "eingebaute" Art wie: this.selectedId = + params ['id']; this.selectedId = + params ['Identifizierung']; Das macht natürlich keinen Sinn und funktioniert nicht.
Phandinhlan
28

Die Antwort von @ StevePaul hat mir sehr gut gefallen, aber wir können das Gleiche tun, ohne einen fremden Anruf zum Abonnieren / Abbestellen zu tätigen.

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
quelle
7
Die Einschränkung bei diesem ist natürlich, dass es sich um den Anfangswert handelt und nachfolgende Änderungen nicht berücksichtigt werden. Wenn Sie also die URL-Parameter programmgesteuert als Teil Ihrer Logik ändern, müssen Sie sich dessen bewusst sein
beidhändig
Ich bin mir nicht sicher, ob sich dies mit späteren Versionen von Angular geändert hat, aber ich sehe es jetzt in this.activatedRoute.snapshot.queryParams
Michael
21

Abfrageparameter senden

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

Abfrageparameter empfangen

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

Offizielle Quelle

dddenis
quelle
Das Lesen funktioniert gut. Aber es wird zwischen Groß- und Kleinschreibung unterschieden. Wie können wir die Groß- und Kleinschreibung nicht berücksichtigen?
Unnie
12

Hallo, Sie können URLSearchParams verwenden. Weitere Informationen finden Sie hier .

importieren:

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

und Funktion:

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

Hinweis : Es wird nicht von allen Plattformen unterstützt und scheint von eckigen Dokumenten im Status "EXPERIMENTELL" zu sein

Asaf Hananel
quelle
2
Das funktioniert bei mir nicht. Ich habe festgestellt, dass window.location.search das führende Fragezeichen der Querystring-Parameter enthält. Dem Schlüssel für den ersten Parameter wird also das Fragezeichen vorangestellt.
AJ Morris
AJ Morris, um Ihr Problem if (window.location.search.indexOf('?') == 0){ normalizedQueryString = window.location.search.substring(1); } else { normalizedQueryString = window.location.search; } let params = new URLSearchParams(normalizedQueryString);
beidhändig
URLSearchParams ist veraltet. Jetzt können Sie dies mit ActivatedRoute tun.
Robert Blasco Villarroya
7

Zunächst einmal habe ich bei der Arbeit mit Angular2 festgestellt, dass die URL mit einer Abfragezeichenfolge lautet /path;query=value1

So greifen Sie auf eine Komponente zu, die Sie verwenden So ist dies, aber jetzt folgt ein Codeblock:

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

Dies ist kein Standardverhalten, warum es beim Laden der Komponente entfernt wird. Ich habe in einem sauberen Testprojekt speziell eingecheckt und wurde nicht umgeleitet oder geändert. Ist es eine Standardroute oder etwas anderes, das das Routing besonders macht?

Weitere Informationen zum Routing mit Abfragezeichenfolgen und Parametern finden Sie im Angular2-Lernprogramm unter https://angular.io/docs/ts/latest/guide/router.html#!#query-parameters

Namirna
quelle
Ich kann keine Parameter wie "; param1 = value1; param2 = value2" verwenden. Dieser Link wurde auf einer anderen Site generiert und auf meiner Site wie "example.com/auth?code_for_auth=askjfbkajdsbfksajdf" umgeleitet
FireGM
Die Art und Weise, wie das Routing derzeit in Angular2 eingerichtet ist, halte ich nicht für wirklich möglich. Eine Art Problemumgehung wird erforderlich sein, da das Routing von Kindern von der Matrix-URL abhängt. Wie ich zumindest weiß. Ich würde es auf meinem Webserver abfangen und sie als Hack verwandeln, scheiße, aber ich kann mir im Moment keinen anderen Weg
vorstellen
Sie haben nicht die Möglichkeit, die Link-Site zu bitten, ihre URL zu ändern?
Namirna
1
Nein, aber ich habe das Problem gelöst, indem ich Location.path () einfach manuell analysiert habe.
FireGM
4
Diese Lösung ist veraltet!
7

Sie können die Abfrageparameter abrufen, wenn Sie die URL mit ActivatedRoute wie folgt übergeben: -

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

}
Saurabh
quelle
7

URL-Parameter als Objekt abrufen.

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

Wenn Sie den Abfrageparameter nur einmal abrufen möchten, verwenden Sie am besten die Methode take , damit Sie sich keine Gedanken über die Abmeldung machen müssen. Hier ist der einfache Ausschnitt: -

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

Hinweis: Entfernen Sie take (1), wenn Sie zukünftig Parameterwerte verwenden möchten.

Abhishek Chandel
quelle
2

jetzt ist es:

this.activatedRoute.queryParams.subscribe((params: Params) => {
  console.log(params);
});
Alan
quelle
1
Vielen Dank für dieses Code-Snippet, das möglicherweise nur begrenzte kurzfristige Hilfe bietet. Eine richtige Erklärung würde ihren langfristigen Wert erheblich verbessern, indem sie zeigt, warum dies eine gute Lösung für das Problem ist, und es für zukünftige Leser mit anderen, ähnlichen Fragen nützlicher machen. Bitte bearbeiten Sie Ihre Antwort, um einige Erklärungen hinzuzufügen, einschließlich der Annahmen, die Sie getroffen haben
Shawn C.
1

Ich hoffe es wird jemand anderem helfen.

Die obige Frage besagt, dass der Wert des Abfrageparameters benötigt wird, nachdem die Seite umgeleitet wurde, und wir können davon ausgehen, dass der Snapshot-Wert (die nicht beobachtbare Alternative) ausreichend wäre.

Niemand hier erwähnte über snapshot.paramMap.get aus der offiziellen Dokumentation .

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

Fügen Sie vor dem Senden Folgendes in die Komponente zum Senden / Umleiten ein:

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

dann wie folgt umleiten ( hier dokumentiert ):

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

oder einfach:

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

Stellen Sie sicher, dass Sie dies in Ihrem Routing-Modul hinzugefügt haben, wie hier dokumentiert :

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

Und schließlich in Ihrer Komponente, die den Abfrageparameter verwenden muss

  • Importe hinzufügen ( hier dokumentiert ):

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

(Die Dokumentation importiert auch switchMap und injiziert Router und HeroService. Sie werden jedoch nur für eine beobachtbare Alternative benötigt. Sie werden NICHT benötigt, wenn Sie eine Snapshot-Alternative wie in unserem Fall verwenden.)

    constructor(
      private route: ActivatedRoute
    ) {}
  • und erhalten Sie den Wert, den Sie benötigen ( hier dokumentiert ):

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

HINWEIS: WENN SIE EINEM ROATING-MODUL EINEM FUNKTIONSMODUL HINZUFÜGEN (WIE IN DER DOKUMENTATION ANGEZEIGT), STELLEN SIE SICHER, DASS IN APP.MODULE.ts DAS ROUTING-MODUL VOR dem AppRoutingModule (oder einer anderen Datei mit App-Routen auf Root-Ebene) IN IMPORTS: [] KOMMT. Andernfalls werden keine Funktionsrouten gefunden (da sie nach {path: '**', redirectTo: '/ not-found'} kommen würden und Sie nur eine nicht gefundene Nachricht sehen würden).

Ula
quelle
1

Sie müssen nur ActivatedRoute in den Konstruktor einfügen und dann einfach auf params oder queryParams zugreifen

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

In einigen Fällen gibt es in NgOnInit nichts ... möglicherweise aufgrund eines Init-Aufrufs vor der Initialisierung von Parametern. In diesem Fall können Sie dies erreichen, indem Sie Observable bitten, mit der Funktion debounceTime (1000) einige Zeit zu warten.

zB =>

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

debounceTime () Gibt einen Wert von der Quelle aus, der erst nach Ablauf einer bestimmten Zeitspanne ohne weitere Quellenemission beobachtet werden kann

Rajiv
quelle
0

Sie können keinen Parameter vom RouterState abrufen, wenn er nicht in der Route definiert ist. In Ihrem Beispiel müssen Sie also den Querystring analysieren ...

Hier ist der Code, den ich verwendet habe:

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

Julien Ricard
quelle
0

Abfrage und Pfad (Winkel 8)

Wenn Sie eine URL wie https://myapp.com/owner/123/show?height=23 haben, verwenden Sie

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

AKTUALISIEREN

Wenn Sie verwenden this.router.navigate([yourUrl]);und Ihre Abfrageparameter in eine yourUrlZeichenfolge eingebettet sind, codiert Angular eine URL und Sie erhalten so etwas wie https://myapp.com/owner/123/show%3Fheight%323 - und die obige Lösung führt zu einem falschen Ergebnis ( queryParams ist leer und Abfrageparameter können an den letzten Pfadparameter geklebt werden, wenn er sich am Pfadende befindet. In diesem Fall wird die Art und Weise der Navigation auf diesem

this.router.navigateByUrl(yourUrl);
Kamil Kiełczewski
quelle