如何从Angular 5中的URL获取查询参数?


181

我使用的是angular 5.0.3,我想使用一堆查询参数来启动我的应用程序/app?param1=hallo&param2=123如何从Angular 2中的url获取查询参数中给出的每个技巧对我不起作用。

任何想法如何获取查询参数的工作?

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

这个私有函数可以帮助我获取参数,但是我认为这不是在新的Angular环境中正确的方法。

[更新:]我的主应用看起来像

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

  constructor(private route: ActivatedRoute) {}

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

您在使用路由器吗?URL来自哪里?
Vinod Bhavnani

是的,有一个ActivatedRoute。我更新了问题以显示主要组件的外观。
拉斯,

您还可以告诉我您的路线常数,在其中设置所有路线吗?
Vinod Bhavnani

const appRoutes:路由= [{路径:“一个”,组件:PageOneComponent},{路径:“”,redirectTo:“ /一个”,pathMatch:“完整”},{路径:“ **”,redirectTo:“ /一个“}]; 我的路线常数。我想在主应用程序中获取所有参数,并将其存储在DTO中,然后导航到其他页面。页面导航按预期方式工作,但我只能通过“ getQueryParameter”功能获得查询参数。在您的问题中,我意识到有些事情我已经忘记了。我是否需要在任何地方标记参数名称?
拉斯,

是的,在您的路线中,您还需要定义参数。如果您在angular.io上查看路由文档,则可以看到它们如何在特定路由上定义参数。像这样的{path:'abc /:param1',component:componentClassName}
Vinod Bhavnani

Answers:


238

在Angular 5中,通过订阅来访问查询参数this.route.queryParams

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

而路径变量由 this.route.snapshot.params

例: /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
根据Angular 6的文档,不鼓励使用ActivatedRoute.queryParams和.params,并且在以后的版本中可能不建议使用。在此处
grreeenn

1
@ShubhenduVaid解释了为什么,他们应该使用ngOnInit而不是构造函数。最佳做法是使用RxJS可观察的对象,然后在使用可观察的对象时使用声明性方法,然后在html上使用异步
coderpatomx

118

这是对我来说最干净的解决方案

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

这很有帮助,谢谢。从角度6.0.8起,我正在使用它,它对我有用:this.route.snapshot.queryParams [“ firstParamKey”]
fluidguid

2
这在Angular8中对我有效。this.route.snapshot.queryParamMap有效。this.route.snapshot.paramMap对我不起作用。
罗密欧·普罗菲特

89

我知道OP要求使用Angular 5解决方案,但是对于所有偶然发现这个问题以寻求更新(6+)Angular版本的人来说。引用Docs,关于ActivatedRoute.queryParams(其他大多数答案都基于):

两个较旧的属性仍然可用。他们的能力不及其替代产品,不建议使用,并且在以后的Angular版本中可能不推荐使用

params —一个Observable,其中包含特定于路线的必需和可选参数。请改用paramMap。

queryParams —一个Observable,包含可用于所有路由的查询参数。请改用queryParamMap。

根据Docs,获取查询参数的简单方法如下所示:

constructor(private route: ActivatedRoute) { }

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

有关更高级的方式(例如,高级组件的重新使用),请参阅文档章节。

编辑:

正如在下面的评论中正确指出的那样,此答案是错误的-至少对于OP指定的情况。

OP要求获取全局查询参数(/ app?param1 = hallo&param2 = 123); 在这种情况下,您应该使用queryParamMap(就像在@ dapperdan1985答案中一样)。

另一方面,paramMap用于特定于路由的参数(例如/ app /:param1 /:param2,结果为/ app / hallo / 123)。

感谢@JasonRoyle和@daka指出这一点。


10
这不应该用于queryParamMapparamMap获取查询字符串参数吗?
詹森·罗伊

2
@JasonRoyle似乎您是正确的,paramMap不起作用。
达卡

1
该答案需要根据上面的评论进行更正。
达卡

@JasonRoyle,达卡,你是对的,谢谢你指出来。更正了答案。
grreeenn

找到完美的工作代码:jsonworld.com/blog/...
瑞里库马里

17

您还可以使用HttpParams,例如:

  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
请澄清一下,我有两个域指向不同的语言站点。本地主机/-> En,本地主机/?lang = fr->法语。我有路由:path: '', redirectTo: '/list' 。this.route.snapshot对我不起作用,因为它redirectTo / list消除了“ lang” queryString。但是这个解决方案对我有用。
Ryan Huang

作为@RyanHuang,我有同样的问题。但是这种解决方案在我的第一个试用版上有效。
Gi1ber7

找到比上述更好的解决方案:jsonworld.com/blog/...
瑞里的Kumari

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

constructor(private route: ActivatedRoute) {}

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

更新

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
这似乎还不够,我得到了ActivatedRouteSnapshot,但是queryParams是一个空对象,params也为空,并且.queryParamMap.get('name')返回null。似乎ngOnInit()太早获得此类查询参数。
拉斯,

实际上,如果您想获得此参数,则应该更改路线。
德米特里·格林科

我有大约10个参数以不同的顺序排列。因此,我必须使用命名查询参数。以及如何设置我的主要AppComponent以实现有10个参数。url / myprogram?a = 1&b = 2&c = 4 ...它表明我有问题吗?是否需要将每个参数路由到其他组件?我希望不是。
拉斯,

你尝试过这个吗?this.route.snapshot.queryParamMap
Dmitry Grinko

1
@DmitryGrinko将实体ID放入路径中并不是一个坏模式,它允许与详细视图的深层链接。
卡尔,


4

当我在寻找类似的解决方案时,偶然发现了这个问题,但是我不需要像完整的应用程序级路由或更多导入的模块之类的东西。

以下代码非常适合我使用,不需要其他模块或导入。

  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 输出:

param1 = hello
param2 = 123

4

查询和路径参数(角度8)

对于https://myapp.com/user/666/read?age=23之类的网址,请使用

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

更新

如果您使用this.router.navigate([someUrl]);且查询参数嵌入someUrl字符串中,然后使用angular对URL进行编码,则得到类似https://myapp.com/user/666/read%3Fage%323的内容 -上述解决方案将产生错误的结果( queryParams将为空,并且路径参数可以粘贴到最后一个路径参数(如果它在路径末端)。在这种情况下,将导航方式更改为此

this.router.navigateByUrl(someUrl);

1
感谢@KamilKiełczewski,您保存我的一天
Tan Nguyen

2

不幸的是,最干净的解决方案不是最可扩展的解决方案。在最新版本的Angular中,在其他答案中建议您可以使用ActivatedRoute Injectible并特别使用以下任一快照属性轻松获取查询参数:

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

或subscription属性(在查询字符串将更新的情况下使用,例如,浏览用户ID):

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

我在这里告诉您这些解决方案具有一个巨大的缺陷,但尚未解决一段时间:https : //github.com/angular/angular/issues/12157

总而言之,唯一的防弹解决方案是使用良好的旧香草javascript。在这种情况下,我创建了一个用于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提供了parseUrl(url:string)方法,该方法将url解析为UrlTree。UrlTree的属性之一是queryParams。因此,您可以执行以下操作:

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

请不要针对不同的问题发布多个相同的答案。有一个关于这种做法的一些有用的建议在这里
大卫·巴克

如果您不需要处理URL更改,即当前URL中已经有参数,请使用此选项。否则,以可观察的方式进行。
汤姆

1

当您有一个空的路由对象时,主要是由于您没有在app.component.html中使用路由器出口。

否则,您将无法获得具有非空子对象(特别是params和queryParams)的有意义的路由对象。

尝试<router-outlet><router-outlet>在致电之前添加 <app-main-component></app-main-component>

在此之前,请确保您已在app-routing中准备好查询参数,然后将其导出App组件使用的Route类:

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

当然,最后一件事,为了获得您的参数,我个人使用this.route.snapshot.params.dynamicParam了dynamicParam是您的应用程序路由组件中使用的名称的方法:)


1

注意您的路线。“ redirectTo”将删除所有查询参数。

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

我使用查询参数“ / main?param1 = a&param2 = b”调用了我的主要组件,并假设我的查询参数在重定向转发生效之前已到达主要组件的“ ngOnInit()”方法中。

但这是错误的。重定向将在之前完成,将查询参数删除,并在没有查询参数的主要组件中调用ngOnInit()方法。

我将路线的第三行更改为

{path: "", component: PageOneComponent},

现在我的查询参数可以在主要组件ngOnInit和PageOneComponent中访问。


1

发现于:父组件从ActivatedRoute获取空参数

为我工作:

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

只是偶然发现了一个相同的问题,这里的大多数答案似乎只能解决Angular内部路由,然后解决其中的一些路由参数与请求参数不同的问题。

我猜想我有一个与Lars原始问题类似的用例。

对我来说,用例例如是引用跟踪:

Angular在运行mycoolpage.com,具有哈希路由,因此mycoolpage.com重定向到mycoolpage.com/#/。对于引用,例如的链接mycoolpage.com?referrer=foo也应该可用。不幸的是,Angular立即剥离了请求参数,直接转到mycoolpage.com/#/

不幸的是,使用空组件+ AuthGuard进行queryParams或进行操作的任何“技巧”都queryParamMap对我不起作用。他们总是空着。

我的hacky解决方案最终是在一个小的脚本中处理此问题,该脚本index.html获得带有请求参数的完整URL 。然后,我通过字符串操作获取请求参数值,并将其设置在window对象上。然后,一个单独的服务处理从窗口对象获取ID的问题。

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

服务

declare var window: any;

@Injectable()
export class ReferrerService {

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

0

简单的解决方案

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

我们可以这样访问订单查询参数:

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

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

还有queryParamMap,它返回一个带paramMap对象的可观察对象。

给定以下路线网址:

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

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

来源-https: //alligator.io/angular/query-parameters/


0

在我看来,Angular 8:

ActivatedRoute.params已取代ActivatedRoute.paramMap ActivatedRoute.queryParams已取代 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

如果您不使用Angular路由器,请查询querystring。安装它

npm install --save querystring

到您的项目。在您的组件中执行以下操作

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

substring(1)之所以必要,是因为如果您有类似这样的内容,'/mypage?foo=bar'则其键名将为?foo

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.