wake-up-neo.com

Angular2-Router behält Abfragezeichenfolge bei

Ich habe eine Angular2 (v2.0.1) -Anwendung geschrieben, die den Router verwendet. Die Website wird mit mehreren Abfragezeichenfolgeparametern geladen, sodass die vollständige URL zunächst wie folgt aussieht:

https://my.application.com/?param1=val1&param2=val2&param3=val3

In meiner Routenkonfiguration habe ich einen Eintrag, der eine leere Route umleitet:

const appRoutes: Routes = [
    {
        path: '',
        redirectTo: '/comp1',
        pathMatch: 'full'
    },
    {
        path: 'comp1',
        component: FirstComponent
    },
    {
        path: 'comp2',
        component: SecondComponent
    }
];

Mein Problem ist, dass nach dem Bootstrapping der App die URL keine Abfrageparameter mehr enthält, sondern wie folgt aussieht:

https://my.application.com/comp1

Gibt es eine Möglichkeit, den Router so zu konfigurieren, dass die erste Abfragezeichenfolge beim Navigieren beibehalten wird?

Vielen Dank
Lukas

36
Lukas Kolletzki

Ich glaube nicht, dass es eine Möglichkeit gibt, dies in der Routenkonfiguration zu definieren. 

Derzeit wird es für routerLinks und zwingend erforderliche Navigation unterstützt 

Sie können eine Wache zur leeren Pfadroute hinzufügen, bei der die Navigation zur /comp1-Route erfolgt.

router.navigate(['/comp1'], { preserveQueryParams: true }); //deprecated see update note
router.navigate(['/comp1'], { queryParamsHandling: "merge" });

Es gibt ein PR , das es erlaubt, preserveQueryParams global zu konfigurieren.

Update-Hinweis: Von https://angular.io/api/router/NavigationExtras ist preserveQueryParams veraltet, verwenden Sie stattdessen queryParamsHandling

37

Wenn Sie mit einer HTML-Vorlage navigieren, können Sie verwenden 

<a [routerLink]="['/page-2']" [routerLinkActive]="['is-active']" queryParamsHandling="merge">

Zu beachten ist, dass queryParamsHandling param keine eckigen Klammern hat.

31
Kamalpreet

Die Antwort von Günter Zöchbauer sollte richtig funktionieren, aber aus irgendeinem Grund funktioniert das bei mir überhaupt nicht. Was am Ende funktionierte, bestand darin, die queryParams direkt zu übergeben, anstatt sie zu "bewahren".

So sieht meine Wache aus:

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    (...)
    this.router.navigate(['login'], { queryParams: route.queryParams });
}
6
AArias

Sie können https://github.com/angular/angular/issues nach einer Funktionsanforderung suchen, die dieser ähnelt. Wenn keine vorhanden ist, senden Sie eine Funktionsanforderung. 

In der Zwischenzeit: Ich glaube, Sie müssen eine Komponente auf dem Pfad: '' erstellen, die nur den Zweck hat, dann zu '/ comp1' umzuleiten, während die QueryString-Parameter erhalten bleiben. 

2
Martin

Der undokumentierte Weg, dies ohne andere Hacks zu tun, ist das Entfernen des führenden Schrägstrichs im Feld "redirectTo". Da Sie den vollständigen Pfad abgleichen, können Sie die Gewissheit haben, dass er das tut, was Sie wollen (d. H. Keine Überraschungs-URL-Segmente). Da es kein absolutes Ziel mehr ist, behält Angular die aktuellen Abfrageparameter bei.

Also in diesem Fall

{
  path: '',
  redirectTo: '/comp1',
  pathMatch: 'full'
}

wird:

{
  path: '',
  redirectTo: 'comp1',
  pathMatch: 'full'
}

Quelle: https://github.com/angular/angular/issues/13315

1
Christopher

erfassen Sie die ursprüngliche URL in -base href-

https://example.com/order?id=123

dann wird es vorherbestehen

https://example.com/order?id=123#/product

0
dot52

Wenn Sie mit einer HTML-Vorlage navigieren, können Sie auch preserveQueryParams="true" verwenden.

Beachten Sie, dass preserveQueryParams ohne eckige Klammer ist.

Z.B: 

<a [routerLink]="['/navigate-to']" preserveQueryParams="true">

0
Vandesh

Es gibt eine Problemumgehung, bei der sekundäre Routen verwendet werden, da Angular diese Routen in der primären Routennavigation beibehalten wird.

Fügen Sie zunächst einen benannten Router-Ausgang in Ihre oberste Komponente ein:

<router-outlet name="params"><router-outlet>

Als Nächstes erstellen Sie eine Dummy-Komponente, an die weitergeleitet werden soll:

@Component({
    template: ""
})
export class ParamsComponent {}

und definieren Sie eine Route, um diese Komponente in der genannten Verkaufsstelle zu instanziieren:

{
    path: ':val1',
    component: ParamsComponent,
    outlet: "params"
}

Ändern Sie Ihre App-Navigation in:

https://my.application.com/(params:val1)

Wenn Sie sich eine ActivatedRoute ansehen, können Sie die Route "params" wie folgt finden:

  var paramsRoute = this.activatedRoute.route.children.find(r => r.outlet == "params");

Wenn paramsRoute den Wert null hat, enthält die URL kein (params: val1).

Dieser nächste Abschnitt wird etwas "hackig", da die sekundäre Route beim ersten Laden nach der primären Route instanziiert wird. Daher kann es vorkommen, dass paramsRoute.snapshot null ist, bis Ihre App vollständig geladen ist. Es gibt eine private Eigenschaft "_futureSnapshot", die die Routenparameter beim ersten Start enthält ... und die gesamte Lebensdauer der App beibehalten wird. Sie erreichen diese, indem Sie Folgendes verwenden:

var queryParams = 
      paramsRoute
      ? paramsRoute["_futureSnapshot"].params
      : {};
var val1 = queryParams["val1"];

Da _futureSnapshot nicht Teil der öffentlichen API ist, ist dies wahrscheinlich ein Feld, das wir nicht verwenden sollten. Wenn Sie sich unwohl fühlen, können Sie wahrscheinlich paramsRoute.params abonnieren. Dies wird Ihre Komponenten jedoch komplizieren.

if (paramsRoute) {
    paramsRoute.params.subscribe(params => {
        this.queryParams = params;
        this.loadData();
    });
} else {
    this.queryParams = {};
    this.loadData();
}

========== ÄNDERUNG ==============

Ich habe einen noch besseren Weg gefunden, die Abfrageparameter abzurufen, der definitiv NICHT icky ist ... Fügen Sie in einer Komponente oder einem Dienst, die instanziiert wird, bevor das Routing auftritt, die folgende Logik hinzu:

    const routeRecognizedSubscription = this.router.events
        .filter(e => e instanceof RoutesRecognized)
        .subscribe((e: RoutesRecognized) => {
            const paramsRoute = e.state.root.children.find(r => r.outlet == "params");
            if (paramsRoute) {
                // capture or use paramsRoute.params 
            }
            routeRecognizedSubscription.unsubscribe();
        });

Dieser Code abonniert vorübergehend RoutesRecognized-Ereignisse, die vor der Navigation auftreten. Nachdem das erste Ereignis empfangen wurde, wird es automatisch abbestellt, da dies nur beim Start der App erforderlich ist.

Beim ersten Ereignis suchen wir nach dem Zustand, der dem Ausgang "params" entspricht. Wenn gefunden, enthält die Eigenschaft params die Daten, die wir benötigen. Kein Zugriff auf private Immobilien.

0
Greg Petrites