Làm cách nào để lấy tham số truy vấn từ URL trong Angular 5?


180

Tôi đang sử dụng 5.0.3 góc, tôi muốn khởi động ứng dụng của mình với một loạt các tham số truy vấn như thế nào /app?param1=hallo&param2=123. Mỗi mẹo được đưa ra trong Cách nhận thông số truy vấn từ url trong Angular 2? không làm việc cho tôi.

Bất kỳ ý tưởng làm thế nào để có được các tham số truy vấn làm việc?

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

Hàm riêng tư này giúp tôi có được các tham số của mình, nhưng tôi không nghĩ rằng đó là cách phù hợp trong môi trường Angular mới.

[cập nhật:] Ứng dụng chính của tôi trông như

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

  constructor(private route: ActivatedRoute) {}

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

Bạn đang sử dụng bộ định tuyến? URL đến từ đâu?
Vinod Bhavnani

Có, có ActivatedRoute. Tôi đã cập nhật câu hỏi của mình để cho thấy thành phần chính của tôi trông như thế nào.
Lars

Bạn cũng có thể chỉ cho tôi tuyến đường của bạn không đổi, nơi bạn đã thiết lập tất cả các tuyến đường?
Vinod Bhavnani

const appRoutes: Routes = [{path: "one", thành phần: PageOneComponent}, {path: "", redirectTo: "/ one", pathMatch: "full"}, {path: "**", redirectTo: "/ một"} ]; Tuyến đường của tôi không đổi. Tôi muốn nhận tất cả các tham số trong ứng dụng chính lưu trữ nó trong DTO, sau đó điều hướng đến một trang khác. Điều hướng trang hoạt động như mong đợi, nhưng tôi chỉ nhận được các tham số truy vấn chính bằng chức năng 'getQueryParameter' của mình. Tôi nhận ra trong câu hỏi của bạn rằng có tồn tại một cái gì đó tôi đã quên. Tôi có cần đánh dấu tên tham số của mình ở bất cứ đâu không?
Lars

Có, trong các tuyến đường của bạn, bạn cũng cần xác định các tham số. Nếu bạn kiểm tra tài liệu định tuyến trên angular.io, bạn có thể thấy cách họ xác định tham số trên một tuyến đường cụ thể. Một cái gì đó như thế này {path: 'abc /: param1', thành phần: thành
phầnClassName

Câu trả lời:


237

Trong Angular 5, các tham số truy vấn được truy cập bằng cách đăng ký this.route.queryParams.

Thí dụ: /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'];
    });
}

trong khi đó, các biến đường dẫn được truy cập bởi this.route.snapshot.params

Thí dụ: /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
Theo tài liệu của Angular 6 , việc sử dụng ActivatedRoute.queryParams và .params không được khuyến khích và có thể không được chấp nhận trong các phiên bản trong tương lai; xem cập nhật tại đây
grreeenn

1
@ShubhenduVaid giải thích tại sao, họ nên sử dụng ngOnInit thay vì hàm tạo. Thực hành tốt nhất sẽ là sử dụng RxJS có thể quan sát được, sau đó sử dụng phương pháp khai báo khi làm việc với các vật quan sát, sau đó sử dụng async trên html
coderpatomx

117

Đây là giải pháp sạch nhất đối với tôi

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

Điều này rất hữu ích, cảm ơn. Kể từ phiên bản 6.0.8, tôi đang sử dụng cái này và nó hoạt động với tôi: this.route.snapshot.queryParams ["firstParamKey"]
liquidguid

2
Điều này làm việc cho tôi trong Angular8. this .route.snapshot.queryParamMap hoạt động. this .route.snapshot.paramMap không hoạt động với tôi.
Romeo Profijt

89

Tôi biết rằng OP đã yêu cầu giải pháp Angular 5, nhưng đối với tất cả các bạn, những người vấp phải câu hỏi này cho các phiên bản Angular mới hơn (6+). Trích dẫn Tài liệu , liên quan đến ActivatedRoute.queryParams (mà hầu hết các câu trả lời khác đều dựa trên):

Hai tài sản cũ vẫn có sẵn. Họ ít có khả năng hơn so với sự thay thế của họ, không được khuyến khích và có thể không được chấp nhận trong phiên bản Angular trong tương lai.

params - Một Observable có chứa các tham số bắt buộc và tùy chọn cụ thể cho tuyến đường. Sử dụng paramMap thay thế.

queryParams - Một Observable có chứa các tham số truy vấn có sẵn cho tất cả các tuyến. Sử dụng queryParamMap thay thế.

Theo Docs , cách đơn giản để nhận thông số truy vấn sẽ như thế này:

constructor(private route: ActivatedRoute) { }

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

Để biết các cách nâng cao hơn (ví dụ: sử dụng lại thành phần nâng cao), hãy xem chương Tài liệu này .

BIÊN TẬP:

Như đã nêu chính xác trong các bình luận bên dưới, câu trả lời này là sai - ít nhất là đối với trường hợp được chỉ định bởi OP.

OP yêu cầu nhận các tham số truy vấn toàn cầu (/ app? Param1 = hallo & param2 = 123); trong trường hợp này, bạn nên sử dụng queryParamMap (giống như trong câu trả lời @ dapperdan1985).

Mặt khác, paramMap được sử dụng cho các tham số dành riêng cho tuyến đường (ví dụ: / app /: param1 /: param2, dẫn đến / app / hallo / 123).

Cảm ơn @JasonRoyle và @daka đã chỉ ra điều đó.


10
Không nên sử dụng queryParamMapkhông paramMapđể tìm nạp các tham số chuỗi truy vấn?
Jason Royle

2
@JasonRoyle Có vẻ như bạn đúng, paramMapkhông hoạt động.
daka

1
Câu trả lời này cần sửa theo các ý kiến ​​trên.
daka

@JasonRoyle, daka, bạn nói đúng, cảm ơn bạn đã chỉ ra điều đó. Sửa câu trả lời.
grreeenn

Tìm thấy mã làm việc hoàn hảo: jsonworld.com/blog/
Soni Kumari

17

Bạn cũng có thể sử dụng HttpParams , chẳng hạn như:

  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
Chỉ cần làm rõ, tôi có hai tên miền trỏ đến trang web ngôn ngữ khác nhau. localhost / -> En, localhost /? lang = fr -> tiếng Pháp. Và tôi có định tuyến : path: '', redirectTo: '/list' . This.route.snapshot không hoạt động với tôi vì nó chuyển hướng / danh sách loại bỏ truy vấn 'lang'. Nhưng giải pháp này hiệu quả với tôi.
Ryan Huang

Là @RyanHuang tôi cũng có vấn đề tương tự. Nhưng giải pháp này đã làm việc trên thử nghiệm đầu tiên của tôi.
Gi1ber7

Tìm giải pháp tốt hơn ở trên: jsonworld.com/blog/ từ
Soni Kumari

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

constructor(private route: ActivatedRoute) {}

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

CẬP NHẬT

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
Điều đó dường như là không đủ, tôi nhận được ActivatedRouteSnapshot nhưng queryParams là một đối tượng trống, params cũng trống và .queryParamMap.get ('name') trả về null. Có vẻ như ngOnInit () quá sớm để có được các tham số truy vấn như vậy.
Lars

thực sự nếu bạn muốn có được thông số này, bạn nên thay đổi lộ trình của mình.
Dmitry Grinko

Tôi có khoảng 10 thông số theo thứ tự khác nhau. Do đó tôi phải sử dụng các tham số truy vấn được đặt tên. Và làm cách nào để thiết lập AppComponent chính của tôi để nhận ra rằng có 10 tham số. url / myprogram? a = 1 & b = 2 & c = 4 ... nó có vấn đề gì không? Tôi có cần định tuyến mọi tham số đến một thành phần khác không? Tôi hy vọng là không.
Lars

Bạn đã thử cái này chưa? this .route.snapshot.queryParamMap
Dmitry Grinko

1
@DmitryGrinko đưa Id thực thể vào tuyến đường không phải là một mẫu xấu, Nó cho phép liên kết sâu đến chế độ xem chi tiết.
Karl


4

Tình cờ gặp phải câu hỏi này khi tôi đang tìm kiếm một giải pháp tương tự nhưng tôi không cần bất cứ thứ gì như định tuyến cấp ứng dụng đầy đủ hoặc các mô-đun nhập khẩu nhiều hơn.

Đoạn mã sau hoạt động tốt cho việc sử dụng của tôi và không yêu cầu thêm mô-đun hoặc nhập.

  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 đầu ra:

param1 = hello
param2 = 123

4

Truy vấn và Params đường dẫn (Angular 8)

Đối với url như https://myapp.com/user/666/read?age=23 sử dụng

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

CẬP NHẬT

Trong trường hợp khi bạn sử dụng this.router.navigate([someUrl]);và các tham số truy vấn của bạn được nhúng trong someUrlchuỗi thì góc sẽ mã hóa một URL và bạn nhận được một cái gì đó như thế này https://myapp.com/user/666/read%3Fage%323 - và giải pháp trên sẽ cho kết quả sai ( queryParams sẽ trống và các tham số đường dẫn có thể được dán vào tham số đường dẫn cuối cùng nếu nó nằm ở cuối đường dẫn). Trong trường hợp này thay đổi cách điều hướng đến này

this.router.navigateByUrl(someUrl);

1
Cảm ơn @Kamil Kiełczewski, bạn đã cứu ngày của tôi
Tan Nguyen

2

Thật không may, giải pháp sạch nhất không phải là giải pháp mở rộng nhất. Trong các phiên bản gần đây của Angular, chúng tôi đề xuất trong các câu trả lời khác là bạn có thể dễ dàng nhận được các tham số truy vấn bằng cách sử dụng ActivatedRoute Methible và đặc biệt sử dụng thuộc tính snapshot:

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

hoặc thuộc tính đăng ký (được sử dụng trong trường hợp chuỗi truy vấn sẽ cập nhật, ví dụ: điều hướng qua id người dùng):

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

Tôi ở đây để nói với bạn rằng các giải pháp này có một lỗ hổng chưa được giải quyết trong một thời gian: https://github.com/angular/angular/issues/12157

Nói chung, giải pháp chống đạn duy nhất là sử dụng javascript vanilla cũ. Trong trường hợp này, tôi đã tạo một dịch vụ để thao tác 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 cung cấp phương thức parseUrl (url: chuỗi) để phân tích url thành UrlTree . Một trong những thuộc tính của UrlTree là queryParams. Vì vậy, bạn có thể làm sth như:

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

Vui lòng không đăng nhiều câu trả lời giống nhau cho các câu hỏi khác nhau. Có một số lời khuyên hữu ích về thực hành này ở đây
David Buck

Sử dụng điều này nếu bạn không cần phải xử lý các thay đổi URL, tức là các tham số đã có sẵn trong URL hiện tại. Làm theo cách có thể quan sát khác.
tom

1

Khi bạn có một đối tượng tuyến đường trống, điều đó chủ yếu là do thực tế là bạn không sử dụng ổ cắm bộ định tuyến trong app.component.html.

Nếu không có điều này, bạn sẽ không thể có được một đối tượng tuyến có ý nghĩa với các mục con không trống, đặc biệt là params & queryParams.

Cố gắng thêm <router-outlet><router-outlet> ngay trước khi gọi <app-main-component></app-main-component>

Trước đó, hãy đảm bảo rằng bạn đã sẵn sàng truy vấn của mình trong định tuyến ứng dụng> xuất khẩu Tuyến đường lớp được sử dụng bởi thành phần Ứng dụng:

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

Tất nhiên, cuối cùng, để có được thông số của bạn, tôi thường sử dụng this.route.snapshot.params.dynamicParamtrong đó DynamicParam là tên được sử dụng trong thành phần định tuyến ứng dụng của bạn :)


1

Hãy cẩn thận với các tuyến đường của bạn. Một "redirectTo" sẽ xóa | bỏ bất kỳ tham số truy vấn nào.

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

Tôi đã gọi thành phần chính của mình bằng các tham số truy vấn như "/ main? Param1 = a & param2 = b và giả sử rằng các tham số truy vấn của tôi đến phương thức" ngOnInit () "trong thành phần chính trước khi chuyển tiếp chuyển hướng có hiệu lực.

Nhưng điều này là sai. Chuyển hướng sẽ đến trước, bỏ các tham số truy vấn đi và gọi phương thức ngOnInit () trong thành phần chính không có tham số truy vấn.

Tôi đã thay đổi dòng thứ ba của tuyến đường của mình thành

{path: "", component: PageOneComponent},

và bây giờ các tham số truy vấn của tôi có thể truy cập được trong các thành phần chính ngOnInit và cả trong PageOneComponent.


1

Tìm thấy trong: Các thành phần cha mẹ nhận được Params trống từ ActivatedRoute

Đã làm cho tôi:

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

Chỉ vấp phải cùng một vấn đề và hầu hết các câu trả lời ở đây dường như chỉ giải quyết nó cho định tuyến bên trong Angular, và sau đó một số trong số chúng cho các tham số tuyến không giống như tham số yêu cầu.

Tôi đoán rằng tôi có một trường hợp sử dụng tương tự như câu hỏi ban đầu của Lars.

Đối với tôi trường hợp sử dụng là ví dụ theo dõi giới thiệu:

Angular chạy trên mycoolpage.com, với định tuyến băm, do đó mycoolpage.comchuyển hướng đến mycoolpage.com/#/. Tuy nhiên, đối với người giới thiệu, một liên kết như vậy mycoolpage.com?referrer=foocũng có thể được sử dụng. Thật không may, Angular ngay lập tức loại bỏ các tham số yêu cầu, trực tiếp đến mycoolpage.com/#/.

Bất kỳ loại 'mẹo' nào khi sử dụng một thành phần trống + AuthGuard và nhận queryParamshoặc queryParamMapkhông, không may, không hoạt động đối với tôi. Họ luôn trống rỗng.

Giải pháp hacky của tôi cuối cùng đã xử lý việc này trong một tập lệnh nhỏ trong index.htmlđó có URL đầy đủ, với các tham số yêu cầu. Sau đó tôi nhận được giá trị param request thông qua thao tác chuỗi và đặt nó trên đối tượng window. Một dịch vụ riêng biệt sau đó xử lý nhận id từ đối tượng cửa sổ.

tập lệnh.html

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

Dịch vụ

declare var window: any;

@Injectable()
export class ReferrerService {

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

0

Giải pháp đơn giản

 // 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 / sản phẩm? order = phổ biến

Chúng ta có thể truy cập thông số truy vấn thứ tự như thế này:

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

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

Ngoài ra còn có queryParamMap, trả về một đối tượng paramMap có thể quan sát được.

Cho URL tuyến đường sau:

http: // localhost: 4200 / sản phẩm? order = phổ biến & bộ lọc = mới

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

Nguồn - https://alligator.io/angular/query-parameter/


0

Tại, tôi nghĩ Angular 8:

ActivatedRoute.paramsđã được thay thế bởi ActivatedRoute.paramMap ActivatedRoute.queryParamsđã được thay thế bởi 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

Nếu bạn không sử dụng bộ định tuyến Angular, hãy thử chuỗi truy vấn . Cài đặt nó

npm install --save querystring

đến dự án của bạn. Trong thành phần của bạn làm một cái gì đó như thế này

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

Điều substring(1)này là cần thiết bởi vì nếu bạn có một cái gì đó như thế này '/mypage?foo=bar'thì tên chính cho sẽ là?foo

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.