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...
  }
}
Lars
źródło
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;
}
Vijayendra Mudigal
źródło
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');
  }
}
dapperdan1985
źródło
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.

grreeenn
źródło
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;
  }
a5tr0
źródło
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
    }
}
Dmitry Grinko
źródło
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);
Kamil Kiełczewski
źródło
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
Trzcina
źródło
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']
        }
    }
}
Donato
źródło
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] || '';
Adam Michalak
źródło
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 :)

andrea06590
źródło
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.

Lars
źródło
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();
  }

}
Yonatan Ayalon
źródło
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;
  }
}
seBaka28
źródło
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")
                  }
Shashwat Gupta
źródło
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/

San Jaisy
źródło
0

Myślę, że w Angular 8:

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

Marvin
źródło
-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);

 });

  }
Kaji Islam
źródło
-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

Chuk Lee
źródło