Jak uzyskać parametry zapytania z adresu URL w Angular 5?


181

Używam Angular 5.0.3, chciałbym uruchomić moją aplikację z kilkoma parametrami zapytania, takimi jak /app?param1=hallo&param2=123. Każda wskazówka podana w artykule Jak uzyskać parametry zapytania z adresu URL w Angular 2? nie działa dla mnie.

Jakieś pomysły, jak uzyskać parametry zapytania?

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

Ta prywatna funkcja pomaga mi uzyskać parametry, ale nie sądzę, że jest to właściwa droga w nowym środowisku Angular.

[aktualizacja:] Moja główna aplikacja wygląda tak

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

  constructor(private route: ActivatedRoute) {}

  ngOnInit(): void {
    // would like to get query parameters here...
    // this.route...
  }
}

Czy używasz routerów? Skąd pochodzi adres URL?
— Vinod Bhavnani

Tak, skorzystaj z ActivatedRoute. Zaktualizowałem moje pytanie, aby pokazać, jak wygląda mój główny komponent.
— Lars

Czy możesz mi też pokazać stałą trasy, na której ustawiłeś wszystkie trasy?
— Vinod Bhavnani

const appRoutes: Routes = [{path: "one", component: PageOneComponent}, {path: "", redirectTo: "/ one", pathMatch: "full"}, {path: "**", redirectTo: "/ one "}]; Moja trasa stała. Chciałbym uzyskać wszystkie parametry w głównej aplikacji, zapisać je w DTO, a następnie przejść do innej strony. Nawigacja po stronach działa zgodnie z oczekiwaniami, ale parametry zapytania otrzymuję tylko przez moją funkcję „getQueryParameter”. W twoim pytaniu zdaję sobie sprawę, że jest coś, o czym zapomniałem. Czy muszę gdziekolwiek zaznaczać nazwy moich parametrów?
— Lars

Tak, w swoich trasach musisz również zdefiniować parametry. Jeśli sprawdzisz dokumenty routingu na angular.io, możesz zobaczyć, jak definiują one parametry na określonej trasie. Coś takiego {ścieżka: 'abc /: param1', komponent: componentClassName}
— Vinod Bhavnani

Odpowiedzi:


238

W Angular 5 dostęp do parametrów zapytania uzyskuje się poprzez subskrybowanie this.route.queryParams.

Przykład: /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'];
    });
}

podczas gdy zmienne ścieżki są dostępne przez this.route.snapshot.params

Przykład: /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;
}

15
Zgodnie z dokumentacją Angular 6 , używanie ActivatedRoute.queryParams i .params jest odradzane i może być przestarzałe w przyszłych wersjach; zobacz aktualizację tutaj
— grreeenn

1
@ShubhenduVaid wyjaśnij, dlaczego powinni używać ngOnInit zamiast konstruktora. Najlepszą praktyką będzie użycie RxJS obserwo walnego, następnie użycie deklaratywnego podejścia podczas pracy z obserwa bami, a następnie użycie async w html
— coderpatomx

118

To dla mnie najczystsze rozwiązanie

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

To jest pomocne, dzięki. Od wersji Angular 6.0.8 używam tego i działa dla mnie: this.route.snapshot.queryParams ["firstParamKey"]
— fluidguid

2
To działa dla mnie w Angular8. this.route.snapshot.queryParamMap działa. this.route.snapshot.paramMap nie działa dla mnie.
— Romeo Profijt

89

Wiem, że OP poprosił o rozwiązanie Angular 5, ale jednak dla wszystkich, którzy natkną się na to pytanie dla nowszych (6+) wersji Angular. Cytując dokumenty dotyczące ActivatedRoute.queryParams (na których opiera się większość innych odpowiedzi):

Dwie starsze usługi są nadal dostępne. Są mniej wydajne niż ich zamienniki, zniechęcone i mogą zostać wycofane w przyszłej wersji Angular.

params - Obserwowalny, który zawiera wymagane i opcjonalne parametry specyficzne dla trasy. Zamiast tego użyj paramMap.

queryParams - obserwowalny, który zawiera parametry zapytania dostępne dla wszystkich tras. Zamiast tego użyj queryParamMap.

Według Docs , prosty sposób uzyskania parametrów zapytania wyglądałby następująco:

constructor(private route: ActivatedRoute) { }

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

Bardziej zaawansowane sposoby (np. Zaawansowane ponowne wykorzystanie komponentów) można znaleźć w tym rozdziale Dokumenty.

EDYTOWAĆ:

Jak słusznie wskazano w komentarzach poniżej, odpowiedź ta jest błędna - przynajmniej w przypadku wskazanym przez OP.

OP prosi o uzyskanie globalnych parametrów zapytania (/ app? Param1 = hallo & param2 = 123); w tym przypadku powinieneś użyć queryParamMap (tak jak w odpowiedzi @ dapperdan1985).

Z drugiej strony paramMap jest używany w parametrach specyficznych dla trasy (np. / app /: param1 /: param2, co daje / app / hallo / 123).

Dzięki @JasonRoyle i @daka za wskazanie tego.


10
Nie powinno to być za pomocą queryParamMapnie paramMapmożna pobrać parametrów ciąg kwerendy?
— Jason Royle

2
@JasonRoyle Wygląda na to, paramMapże masz rację, nie działa.
— daka

1
Ta odpowiedź wymaga korekty zgodnie z komentarzami powyżej.
— daka

@JasonRoyle, daka, masz rację, dziękuję za wskazanie tego. Poprawiono odpowiedź.
— grreeenn

Znalazłem doskonały działający kod: jsonworld.com/blog/…
— Soni Kumari

17

Możesz również użyć HttpParams , takich jak:

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

1
Wyjaśnij, mam dwie domeny wskazujące na witrynę w innym języku. localhost / -> En, localhost /? lang = fr -> francuski. I mam trasy: path: '', redirectTo: '/list' . This.route.snapshot nie działa dla mnie, ponieważ przekierowuje do / list, co eliminuje ciąg zapytania „lang”. Ale to rozwiązanie działa dla mnie.
— Ryan Huang

Jako @RyanHuang mam podobny problem. Ale to rozwiązanie zadziałało na mojej pierwszej próbie.
— Gi1ber7

Znajdź lepsze rozwiązanie niż powyżej: jsonworld.com/blog/…
— Soni Kumari

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

constructor(private route: ActivatedRoute) {}

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

AKTUALIZACJA

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

6
to wydaje się niewystarczające, otrzymuję ActivatedRouteSnapshot, ale queryParams jest pustym obiektem, parametry również są puste, a .queryParamMap.get ('name') zwraca wartość null. Wygląda na to, że ngOnInit () jest zbyt wcześnie, aby uzyskać takie parametry zapytania.
— Lars

właściwie jeśli chcesz uzyskać te parametry, powinieneś zmienić trasę.
— Dmitry Grinko

Mam około 10 parametrów w innej kolejności. Dlatego muszę używać nazwanych parametrów zapytania. I jak ustawić mój główny komponent AppComponent, aby zdawał sobie sprawę, że jest 10 parametrów. url / myprogram? a = 1 & b = 2 & c = 4 ... wygląda na to, że mam problem? Czy muszę kierować każdy parametr do innego składnika? Mam nadzieję, że nie.
— Lars

Czy próbowałeś tego? this.route.snapshot.queryParamMap
— Dmitry Grinko

1
@DmitryGrinko umieszczenie identyfikatora podmiotu w trasie nie jest złym wzorcem, pozwala na głębokie łącze do widoku szczegółowego.
— Karl


5

Parametry zapytania i ścieżki (Angular 8)

W przypadku adresu URL takiego jak https://myapp.com/user/666/read?age=23 użyj

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

AKTUALIZACJA

W przypadku, gdy używasz, this.router.navigate([someUrl]);a parametry zapytania są osadzone w someUrlciągu znaków, angular koduje adres URL i dostajesz coś takiego https://myapp.com/user/666/read%3Fage%323 - a powyższe rozwiązanie da zły wynik ( queryParams będzie pusta, a parametry ścieżki można przykleić do ostatniego parametru ścieżki, jeśli znajduje się na końcu ścieżki). W takim przypadku zmień sposób nawigacji na ten

this.router.navigateByUrl(someUrl);

1
Dziękuję @Kamil Kiełczewski, ratujesz mi dzień
— Tan Nguyen

4

Natknąłem się na to pytanie, gdy szukałem podobnego rozwiązania, ale nie potrzebowałem niczego takiego jak routing na poziomie aplikacji lub więcej zaimportowanych modułów.

Poniższy kod działa świetnie do mojego użytku i nie wymaga żadnych dodatkowych modułów ani importów.

  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 wyjścia:

param1 = hello
param2 = 123

2

Niestety, najczystsze rozwiązanie nie jest rozwiązaniem najbardziej rozszerzalnym. W ostatnich wersjach Angular sugeruje się, że w innych odpowiedziach można łatwo uzyskać parametry zapytania za pomocą metody ActivatedRoute Injectible i specjalnie wykorzystując jedną z właściwości migawki:

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

lub właściwość subscribe (używana w przypadkach, gdy ciąg zapytania zostanie zaktualizowany, np. podczas nawigacji po identyfikatorach użytkowników):

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

Jestem tutaj, aby powiedzieć, że te rozwiązania mają ziejącą wadę, która nie została rozwiązana od jakiegoś czasu: https://github.com/angular/angular/issues/12157

Podsumowując, jedynym rozwiązaniem jest użycie starego, dobrego, waniliowego javascript. W tym przypadku stworzyłem usługę do manipulacji adresem 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']
        }
    }
}

2

Angular Router udostępnia metodę parseUrl (url: string), która analizuje adres URL w UrlTree . Jedną z właściwości UrlTree są queryParams. Więc możesz zrobić coś takiego:

this.router.parseUrl(this.router.url).queryParams[key] || '';

Nie publikuj wielu identycznych odpowiedzi na różne pytania. Oto
— David Buck

Użyj tego, jeśli nie musisz zajmować się zmianami adresu URL, tj. Parametry są już dostępne w bieżącym adresie URL. Zrób to w widoczny sposób, inaczej.
— tom

1

Gdy masz pusty obiekt trasy, wynika to głównie z faktu, że nie używasz gniazda routera w swoim app.component.html.

Bez tego nie będziesz w stanie uzyskać znaczącego obiektu trasy z niepustymi subObjectami, szczególnie params & queryParams.

Spróbuj dodać <router-outlet><router-outlet>tuż przed telefonem <app-main-component></app-main-component>

Wcześniej upewnij się, że masz gotowy parametr zapytania w routingu aplikacji,> który eksportuje klasę Route używaną przez składnik aplikacji:

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

Ostatnią rzeczą, oczywiście, aby uzyskać parametr, osobiście używam, this.route.snapshot.params.dynamicParamgdzie dynamicParam jest nazwą używaną w komponencie routingu aplikacji :)


1

Uważaj na swoje trasy. „RedirectTo” usunie | upuści każdy parametr zapytania.

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

Wywołałem mój główny komponent z parametrami zapytania, takimi jak „/ main? Param1 = a & param2 = b, i założyłem, że parametry zapytania docierają do metody„ ngOnInit () ”w głównym komponencie, zanim przekierowanie zacznie działać.

Ale to jest złe. Przekierowanie pojawiło się wcześniej, porzuca parametry zapytania i wywołuje metodę ngOnInit () w głównym komponencie bez parametrów zapytania.

Zmieniłem trzecią linię moich tras na

{path: "", component: PageOneComponent},

a teraz moje parametry zapytania są dostępne w głównych komponentach ngOnInit, a także w PageOneComponent.


1

Znalezione w: Komponenty nadrzędne otrzymują puste Params z ActivatedRoute

Pracował dla mnie:

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

}

0

Natknąłem się tylko na ten sam problem i większość odpowiedzi wydaje się rozwiązywać go tylko dla wewnętrznego routingu Angular, a następnie niektóre z nich dla parametrów trasy, które nie są takie same jak parametry żądania.

Zgaduję, że mam podobny przypadek użycia do oryginalnego pytania Larsa.

Dla mnie przypadek użycia to np. Śledzenie skierowań:

Angular działa na mycoolpage.com, z routingiem skrótu, więc mycoolpage.comprzekierowuje do mycoolpage.com/#/. Jednak w przypadku skierowania link taki jak mycoolpage.com?referrer=foopowinien być również użyteczny. Niestety, Angular natychmiast usuwa parametry żądania, przechodząc bezpośrednio do mycoolpage.com/#/.

Wszelkiego rodzaju „sztuczki” z użyciem pustego komponentu + AuthGuard i otrzymaniem queryParamslub wykonaniem queryParamMap, niestety, nie działały dla mnie. Zawsze były puste.

Moje zmyślone rozwiązanie polegało na tym, że załatwiłem to w małym skrypcie, w index.htmlktórym pobiera się pełny adres URL z parametrami żądania. Następnie otrzymuję wartość parametru żądania poprzez manipulację ciągiem i ustawiam ją na obiekcie okna. Następnie oddzielna usługa obsługuje pobieranie identyfikatora z obiektu okna.

index.html skrypt

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

Usługa

declare var window: any;

@Injectable()
export class ReferrerService {

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

0

Proste rozwiązanie

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

0

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

Możemy uzyskać dostęp do parametru zapytania zamówienia w następujący sposób:

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

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

Istnieje również queryParamMap, który zwraca obserwowalny obiekt paramMap.

Biorąc pod uwagę następujący adres URL trasy:

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

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

Źródło - https://alligator.io/angular/query-parameters/


0

Myślę, że w Angular 8:

ActivatedRoute.paramszostał zastąpiony przez ActivatedRoute.paramMap ActivatedRoute.queryParamszostał zastąpiony przez ActivatedRoute.queryParamMap


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

 });

  }

-9

Jeśli nie używasz routera Angular, spróbuj, querystring . Zainstaluj to

npm install --save querystring

do swojego projektu. W swoim komponencie zrób coś takiego

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

Jest substring(1)to konieczne, ponieważ jeśli masz coś takiego, '/mypage?foo=bar'nazwa klucza będzie?foo

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.