¿Cómo obtener parámetros de consulta de url en Angular 2?

237

Yo uso angular2.0.0-beta.7. Cuando un componente se carga en una ruta a la /path?query=value1que se redirige /path. ¿Por qué se eliminaron los parámetros GET? ¿Cómo puedo preservar los parámetros?

Tengo un error en los enrutadores. Si tengo una ruta principal como

@RouteConfig([
  {
      path: '/todos/...',
      name: 'TodoMain',
      component: TodoMainComponent
  }
])

y mi hijo ruta como

@RouteConfig([
  { path: '/', component: TodoListComponent, name: 'TodoList', useAsDefault:true },
  { path: '/:id', component: TodoDetailComponent, name:'TodoDetail' }
])

entonces no puedo obtener parámetros en TodoListComponent. Soy capaz de conseguir

params("/my/path;param1=value1;param2=value2") 

pero quiero el clásico

query params("/my/path?param1=value1&param2=value2")
FireGM
fuente
1
¿Cómo lo especificaste @RouteConfigpara esto path?
Pankaj Parkar
Encontré error. Tengo la ruta principal y la ruta secundaria y si tengo la ruta principal como {ruta: '/ todos / ...', nombre: 'TodoMain', componente: TodoMainComponent} y ruta secundaria {ruta: '/', componente: TodoListComponent, nombre: 'TodoList', useAsDefault: true}, no funciona y redirige a url sin parámetros de consulta.
FireGM

Respuestas:

412

Al inyectar una instancia de ActivatedRouteuno, puede suscribirse a una variedad de observables, incluidos ay queryParamsun paramsobservable:

import {Router, ActivatedRoute, Params} from '@angular/router';
import {OnInit, Component} from '@angular/core';

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

  constructor(private activatedRoute: ActivatedRoute) {}

  ngOnInit() {
    // Note: Below 'queryParams' can be replaced with 'params' depending on your requirements
    this.activatedRoute.queryParams.subscribe(params => {
        const userId = params['userId'];
        console.log(userId);
      });
  }

}

UNA NOTA RELATIVA A SUSCRIBIRSE

@Reto y @ codef0rmer habían señalado con razón que, según los documentos oficiales, un método unsubscribe()interno de componentes onDestroy()es innecesario en este caso. Esto ha sido eliminado de mi código de muestra. (Ver cuadro de alerta azul en este tutorial)

Stephen Paul
fuente
2
Sugiero además reemplazar la suscripción con una promesa, en este caso especial. this.activatedRoute.params.toPromise () .then (response => ...) .catch (error => ...);
dic
¿Dónde puedo pasar "activeRoute"?
michali el
20
De la documentación oficial: ¿Necesito darme de baja? The Router manages the observables it provides and localizes the subscriptions. The subscriptions are cleaned up when the component is destroyed, protecting against memory leaks, so we don't need to unsubscribe from the route params Observable.
Reto
redireccionamientos angulares sin disparar la suscripción (o promesa). Puedo ver la devolución de llamada original con el token, pero luego redirige a la ruta sin los parámetros de consulta y console.log (param) es solo un objeto vacío.
FlavorScape
1
@Sobhan, sí, hay una diferencia. El operador switchMap devuelve un Observable mientras que el operador de suscripción permite que el observador (nuestro componente) vea los elementos que finalmente emite un Observable. Entonces, en los documentos, se emplean 2 instancias de switchmap. 1) Han usado switchMap para agregar una solicitud de héroes. SwitchMap, a diferencia de la suscripción, se asegurará de que la solicitud se cancele si el usuario vuelve a navegar a la ruta mientras recupera un héroe. 2) Se utiliza una tubería asíncrona. Las tuberías asincrónicas consumen un observable, por lo que no se debe suscribir (la tubería asincrónica lo hará por usted).
Stephen Paul
103

Cuando una URL como esta http://stackoverflow.com?param1=value

Puede obtener el param1 por código siguiente:

import { Component, OnInit } from '@angular/core';
import { Router, ActivatedRoute, Params } from '@angular/router';

@Component({
    selector: '',
    templateUrl: './abc.html',
    styleUrls: ['./abc.less']
})
export class AbcComponent implements OnInit {
    constructor(private route: ActivatedRoute) { }

    ngOnInit() {
        // get param
        let param1 = this.route.snapshot.queryParams["param1"];
    }
}
Trung
fuente
2
¿significa esto que ya no necesita agregar el "/: id" en la ruta routeconfig? porque me pongo "indefinido" cuando uso esto, así que todavía debo tener un error en alguna parte
Axelle
2
Excelente. Esto era lo que estaba buscando porque necesito leer los parámetros directamente desde una url de servidor dinámico. No puedo usar navegar.
The.Bear
37

Aunque la pregunta especifica la versión beta 7 , esta pregunta también aparece como resultado de búsqueda superior en Google para frases comunes como parámetros de consulta angular 2 . Por esa razón, aquí hay una respuesta para el enrutador más nuevo (actualmente en alpha.7 ).

La forma en que se leen los parámetros ha cambiado dramáticamente. Primero necesita inyectar la dependencia llamada Routeren los parámetros de su constructor como:

constructor(private router: Router) { }

y después de eso podemos suscribirnos a los parámetros de consulta en nuestro ngOnInitmétodo (el constructor también está bien, pero ngOnInitdebe usarse para la comprobabilidad) como

this.router
  .routerState
  .queryParams
  .subscribe(params => {
    this.selectedId = +params['id'];
  });

En este ejemplo, leemos el ID del parámetro de consulta de URL como example.com?id=41.

Todavía hay pocas cosas que notar:

  1. Acceder a la propiedad de paramslike params['id']siempre devuelve una cadena , y esta se puede convertir en número con el prefijo+ .
  2. La razón por la cual los parámetros de consulta se obtienen con observable es que permite reutilizar la misma instancia de componente en lugar de cargar una nueva. Cada vez que se cambia el parámetro de consulta, provocará un nuevo evento al que nos hemos suscrito y, por lo tanto, podemos reaccionar ante los cambios en consecuencia.
Roope Hakulinen
fuente
¿Hay alguna manera de tener múltiples parámetros yendo al mismo miembro? Por ejemplo, me gustaría 'id' o 'identificación' para ir a this.selectedId.
phandinhlan
@phandinhlan: Bueno, esa no es realmente una pregunta relacionada con Angular 2. Por supuesto, puede implementarse, pero debe definir la lógica usted mismo. Básicamente, lo que desea hacer es verificar primero si la primera clave está definida y solo luego leer el valor de ella, y si no, leer el valor con otra clave. Esto podría lograrse con algo así if (params.hasOwnProperty('id')) { this.selectedId = params['id'] } else { this.selectedId = params['identification']}.
Roope Hakulinen
Sí, terminé haciendo algo así. Solo pensé que habría alguna forma "integrada" como: this.selectedId = + params ['id']; this.selectedId = + params ['identificación']; Por supuesto, eso no tiene ningún sentido y no funciona.
phandinhlan
28

Realmente me gustó la respuesta de @ StevePaul, pero podemos hacer lo mismo sin una llamada de suscripción / cancelación de suscripción.

import { ActivatedRoute } from '@angular/router';
constructor(private activatedRoute: ActivatedRoute) {
    let params: any = this.activatedRoute.snapshot.params;
    console.log(params.id);
    // or shortcut Type Casting
    // (<any> this.activatedRoute.snapshot.params).id
}
codef0rmer
fuente
77
La advertencia, por supuesto, con este es que será el valor inicial y los cambios posteriores no se reflejarán. Entonces, si está cambiando los parámetros de URL mediante programación como parte de su lógica, es algo que debe tener en cuenta
ambidiestro el
No estoy seguro de si esto cambió con versiones posteriores de Angular, pero ahora lo veo en this.activatedRoute.snapshot.queryParams
Michael
21

Para enviar parámetros de consulta

import { Router } from '@angular/router';
this.router.navigate([ '/your-route' ], { queryParams: { key: va1, keyN: valN } });

Para recibir parámetros de consulta

import { ActivatedRoute } from '@angular/router';
this.activatedRoute.queryParams.subscribe(params => {
    let value_1 = params['key'];
    let value_N = params['keyN'];
});

Fuente oficial

dddenis
fuente
La lectura funciona bien, pero distingue entre mayúsculas y minúsculas. ¿Cómo podemos hacer que no distinga entre mayúsculas y minúsculas?
Unnie
12

Hola, puedes usar URLSearchParams, puedes leer más sobre esto aquí .

importar:

import {URLSearchParams} from "@angular/http";

y función:

getParam(){
  let params = new URLSearchParams(window.location.search);
  let someParam = params.get('someParam');
  return someParam;
}

Aviso : no es compatible con todas las plataformas y parece estar en estado "EXPERIMENTAL" por documentos angulares

Asaf Hananel
fuente
2
Esto no funciona para mi. Descubrí que window.location.search incluye el signo de interrogación principal de los parámetros de la cadena de consulta. Entonces, la clave para el primer parámetro tendrá el signo de interrogación antepuesto.
AJ Morris
AJ Morris, para solucionar su problema: if (window.location.search.indexOf('?') == 0){ normalizedQueryString = window.location.search.substring(1); } else { normalizedQueryString = window.location.search; } let params = new URLSearchParams(normalizedQueryString);
ambidiestro
URLSearchParams está en desuso. Ahora puedes hacerlo con ActivatedRoute.
Robert Blasco Villarroya
7

En primer lugar, lo que he encontrado trabajando con Angular2 es que la url con una cadena de consulta sería /path;query=value1

Para acceder a él en un componente que usa So es esto, pero ahora sigue un bloque de código:

    constructor(params: RouteParams){
    var val = params.get("query");
    }

En cuanto a por qué se eliminaría cuando cargue el componente, ese no es el comportamiento predeterminado. Verifiqué específicamente en un proyecto de prueba limpio y no fui redirigido ni cambiado. ¿Es una ruta predeterminada o algo más que es especial sobre el enrutamiento?

Lea sobre el enrutamiento con cadenas de consulta y parámetros en el Tutorial de Angular2 en https://angular.io/docs/ts/latest/guide/router.html#!#query-parameters

Namirna
fuente
No puedo usar parámetros como "; param1 = value1; param2 = value2", este enlace generado en otro sitio y redirigir en mi sitio como "example.com/auth?code_for_auth=askjfbkajdsbfksajdf"
FireGM
La forma en que se configura el enrutamiento en Angular2 en este momento, no creo que sea realmente posible. Se necesitará algún tipo de solución ya que el enrutamiento secundario depende de la URL de la matriz. En cuanto a lo que sé al menos. Lo interceptaría en mi servidor web y los transformaría como un truco, es una mierda, pero no puedo pensar en otra forma en este momento
Namirna
¿No tiene la posibilidad de pedirle al sitio de enlace que cambie su URL?
Namirna
1
No. Pero resolví el problema simplemente analizando manualmente Location.path ()
FireGM
44
esta solución en desuso!
7

Puede obtener los parámetros de consulta cuando se pasa en URL usando ActivatedRoute como se indica a continuación: -

url: - http: /dominio.com? prueba = abc

import { Component } from '@angular/core';
import { ActivatedRoute }     from '@angular/router';

@Component({
  selector: 'my-home'
})
export class HomeComponent {

  constructor(private sharedServices : SharedService,private route: ActivatedRoute) { 
    route.queryParams.subscribe(
      data => console.log('queryParams', data['test']));
  }

}
Saurabh
fuente
7

Obtener URL param como un objeto.

import { Router } from '@angular/router';
constructor(private router: Router) {
    console.log(router.parseUrl(router.url));
}
Jsonras
fuente
2

Si solo desea obtener el parámetro de consulta una vez, la mejor manera es usar el método take para no tener que preocuparse por la cancelación de la suscripción. Aquí está el fragmento simple: -

constructor(private route: ActivatedRoute) {
  route.snapshot.queryParamMap.take(1).subscribe(params => {
     let category = params.get('category')
     console.log(category);
  })
}

Nota: Elimine take (1) si desea usar valores de parámetros en el futuro.

Lámpara Abhishek
fuente
2

ahora es:

this.activatedRoute.queryParams.subscribe((params: Params) => {
  console.log(params);
});
Alan
fuente
1
Gracias por este fragmento de código, que podría proporcionar una ayuda limitada a corto plazo. Una explicación adecuada mejoraría enormemente su valor a largo plazo al mostrar por qué esta es una buena solución al problema y la haría más útil para futuros lectores con otras preguntas similares. Edite su respuesta para agregar alguna explicación, incluidas las suposiciones que ha hecho
Shawn C.
1

Espero que ayude a alguien más.

La pregunta anterior establece que el valor del parámetro de consulta es necesario después de que la página ha sido redirigida y podemos suponer que el valor de la instantánea (la alternativa no observable) sería suficiente.

Nadie aquí mencionó acerca de snapshot.paramMap.get de la documentación oficial .

this.route.snapshot.paramMap.get('id')

Entonces, antes de enviarlo, agregue esto en el componente de envío / redireccionamiento:

import { Router } from '@angular/router';

luego redirija como cualquiera (documentado aquí ):

this.router.navigate(['/heroes', { id: heroId, foo: 'foo' }]);

o simplemente:

this.router.navigate(['/heroes', heroId ]);

Asegúrese de haber agregado esto en su módulo de enrutamiento como se documenta aquí :

 { path: 'hero/:id', component: HeroDetailComponent }

Y finalmente, en su componente que necesita usar el parámetro de consulta

  • agregar importaciones (documentado aquí ):

    import { Router, ActivatedRoute, ParamMap } from '@angular/router';
  • inyectar ruta activada

(la documentación también importa switchMap y también inyecta Router y HeroService, pero son necesarios solo para una alternativa observable; NO son necesarios cuando se utiliza la alternativa de instantánea como en nuestro caso):

    constructor(
      private route: ActivatedRoute
    ) {}
  • y obtenga el valor que necesita (documentado aquí ):

    ngOnInit() {
      const id = this.route.snapshot.paramMap.get('id');
    }

NOTA: SI AGREGA EL MÓDULO DE ENRUTAMIENTO A UN MÓDULO DE CARACTERÍSTICAS (COMO SE MUESTRA EN LA DOCUMENTACIÓN) ASEGÚRESE DE QUE EN APP.MODULE.ts ESTE MÓDULO DE ENRUTAMIENTO VIENE ANTES de AppRoutingModule (u otro archivo con rutas de aplicación de nivel raíz) EN IMPORTACIONES: []. DE LO CONTRARIO, NO SE ENCONTRARÁN RUTAS DE CARACTERÍSTICAS (COMO LLEGARÍAN DESPUÉS de {ruta: '**', redirigir a: '/ no encontrado'} y solo verá un mensaje no encontrado).

Ula
fuente
1

Solo necesita inyectar ActivatedRoute en el constructor y luego simplemente acceder a los parámetros o queryParams sobre él

constructor(private route:ActivatedRoute){}
ngOnInit(){
        this.route.queryParams.subscribe(params=>{
        let username=params['username'];
      });
 }

En algunos casos, no da nada en NgOnInit ... tal vez debido a la llamada de inicio antes de la inicialización de los parámetros, en este caso puede lograrlo pidiéndole a un observable que espere un tiempo por la función debounceTime (1000)

eg =>

 constructor(private route:ActivatedRoute){}
    ngOnInit(){
            this.route.queryParams.debounceTime(100).subscribe(params=>{
            let username=params['username'];
          });
     }

debounceTime () Emite un valor de la fuente observable solo después de un lapso de tiempo particular pasado sin otra emisión de fuente

Rajiv
fuente
0

No puede obtener un parámetro de RouterState si no está definido en la ruta, por lo que en su ejemplo, debe analizar la cadena de consulta ...

Aquí está el código que usé:

let re = /[?&]([^=#&]+)=([^&#]*)/g;
let match;
let isMatch = true;
let matches = [];
while (isMatch) {
    match = re.exec(window.location.href);
    if (match !== null) {
        matches[decodeURIComponent(match[1])] = decodeURIComponent(match[2]);
        if (match.index === re.lastIndex) {
            re.lastIndex++;
        }
    }
    else {
        isMatch = false;
    }
}
console.log(matches);

Julien Ricard
fuente
0

Consulta y ruta (angular 8)

Si tiene una URL como https://myapp.com/owner/123/show?height=23 , use

combineLatest( [this.route.paramMap, this.route.queryParamMap] )
  .subscribe( ([pathParams, queryParams]) => {
    let ownerId = pathParams.get('ownerId');    // =123
    let height  = queryParams.get('height');    // =height
    // ...
  })

ACTUALIZAR

En caso de que use this.router.navigate([yourUrl]);y sus parámetros de consulta estén incrustados en una yourUrlcadena, entonces angular codifica una URL y obtiene algo como esto https://myapp.com/owner/123/show%3Fheight%323 - y la solución anterior dará un resultado incorrecto ( queryParams estará vacío, y los parámetros de consulta se pueden pegar al último parámetro de ruta si está en el extremo de la ruta). En este caso, cambie la forma de navegación a este

this.router.navigateByUrl(yourUrl);
Kamil Kiełczewski
fuente