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

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)


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"];
    }
}

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.

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
}

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


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


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


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

}

7

URL-Parameter als Objekt abrufen.

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

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.


2

jetzt ist es:

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

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


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


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


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);
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.