5

Is there some way to get this kind of URL in Angular 2?

http://example.com/the-route?param[]=value1&param[]=value2&param[]=value3

I'm trying to do it like it should be, using queryParams with the Router, but as queryParams accepts an Object I can't do this:

this.router.navigate(['/the-route'], queryParams: { 'param[]': 'value1', 'param[]': 'value2', 'param[]': 'value3' });

Because, of course, I can't use the same name (param[]) several times in the Object

I'm struggling with how to do this, but can't find a way

I've seen this post: Angular 2 pass array to router queryString. But there are no correct answers

BinaryButterfly
  • 18,137
  • 13
  • 50
  • 91
Antop
  • 123
  • 1
  • 1
  • 9
  • I think the question should be; why would you want a your params in that format? Router naviagtion is only meant for local navigation, this link (with params) will never end up on the server. Are you sure you're looking for local nav? Or do you want to do a server call here (then i can understand the array format)? – MikeOne Feb 23 '17 at 10:27
  • Yes MikeOne, I want to do a Server Call via a Service to retrieve some json data – Antop Feb 23 '17 at 19:19
  • Via a service? Okay. You're navigating here to a set route that probably uses a component. Where does the service (you mean an Angular service here?) happen? My point is, if your server expects this GET format, you should resolve in ia service. A router call will just route this data to another component, where you would have to parse it again etc. Maybe I'm not understanding what you're trying to achieve here.. – MikeOne Feb 24 '17 at 21:23
  • Well @MikeOne, I'm intending to do **something similar to the Airbnb site**. As you change your search preferences in the Search Form Component, the URL of the page changes to reflect those preferences. And then the Main Component, who is subscribed to the ActivatedRoute, makes a call to the Service with the queryParams. And the Service makes a call to the API. The API returns the Json data. This Json data is sended back to the Main Component via a subscription. And the Main Component renders the data in the template. Maybe sounds complicated, but It's pretty simple. – Antop Feb 25 '17 at 08:50
  • I understand what you want I think, but why would you specifically use that repeating data format in the GET string (airbnb doesn't!) – MikeOne Feb 25 '17 at 11:43
  • @MikeOne, Airbnb uses to set the RoomType for example, like: [link](https://www.airbnb.es/s/Madrid?room_types[]=Entire%20home%2Fapt&room_types[]=Private%20room&room_types[]=Shared%20room&guests=1&adults=1&children=0&infants=0&place_id=ChIJgTwKgJcpQg0RaSKMYcHeNsQ&ss_id=l63mo6pv&source=bb&page=1&allow_override%5B%5D=&ne_lat=40.42209867510085&ne_lng=-3.6845693441191543&sw_lat=40.357634979537146&sw_lng=-3.728943810061537&zoom=14) – Antop Feb 25 '17 at 17:05
  • Okay, if you really want to this, you probably can, but is it okay to do if via your component and than pass it to your template? If so, I can probably come up with a working example for you.. – MikeOne Feb 25 '17 at 19:02
  • @Antop Please, see this one. https://stackoverflow.com/questions/41264722/how-to-handle-multiple-queryparams-in-angular2 It is solved there. – Skyware Sep 08 '17 at 15:11
  • Many thanks @Skyware for the heads-up. It says something about the ugliness of the url, don't know what they mean. I will try it – Antop Sep 09 '17 at 16:39

5 Answers5

4

Yo can do like this:

let object1 = {
  'name':'Charles',
  'age':21,
}

let params = {
  'student':JSON.stringify(object1),
  'carreer':'law',
}

this.router.navigate(['/the-route'], {queryParams: params});

and when you receive the 'student' param you just PARSE IT like this:

let student = JSON.parse (params['student']);

and that's it!

Ari Waisberg
  • 1,186
  • 1
  • 12
  • 23
2

There is no possibility to do this right now.

If You trace the router code yourself begining from router#navigate(), You can see that create_url_tree#tree() function builds a tree with stringified queryParams:

function tree(oldSegmentGroup, newSegmentGroup, urlTree, queryParams, fragment) {
  if (urlTree.root === oldSegmentGroup) {
    return new UrlTree(newSegmentGroup, stringify(queryParams), fragment);
  }
  return new UrlTree(replaceSegment(urlTree.root, oldSegmentGroup, newSegmentGroup), stringify(queryParams), fragment);
}

And stringify() does all the dirty work:

function stringify(params) {
  var /** @type {?} */ res = {};
  forEach(params, function (v, k) { return res[k] = "" + v; });
  return res;
}

Result of concatenation of string and array is a comma-delimited string.

There are a couple of issues about multiple query parameters with the same name, that was fixed in https://github.com/angular/angular/pull/11373. As You can see, modified url_tree#serializeQueryParams() does exactly what You need. But the problem is that serialization takes place a lot later as the tree will be built.

It seems that this is a bug in create_url_tree#tree() - it shouldn't stringify query params, because it is the area of responsibility of url_tree#serializeQueryParams(). I've removed call to stringify() locally and everything started working as it should.

As workaround You can stringify each query parameter manually with JSON.stringify(queryParamArray) before sending it to router#naviagate() and parse it with JSON.parse(param) in route.queryParams.subscribe(). URL looks horrible, but now it's the only way to pass arrays.

UPDATE: I created the issue in the angular repository: https://github.com/angular/angular/issues/14796

1

You can pass them as items in the router commands array:

[routerLink]="['/Questions', {queryParams: {id:1234, pageid:0}} ]"

See also https://angular.io/docs/ts/latest/guide/router.html#!#query-parameters

  • Sorry Rakesh, I wanted to do it inside the Component, not in the Template. Anyway, that's exactly the way I was doing, passing queryParams to the Router via an Object – Antop Feb 23 '17 at 19:24
1

you can use the navigation extras hope this might help you:

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

function(){
 let extra: any = [];


  let navigationExtras: NavigationExtras = {
      queryParams:extra
    };

 this.router.navigate(['/Questions'], navigationExtras);
}
Shailesh kala
  • 1,618
  • 18
  • 16
-1

Not a lot related to the question, but might help people who come to this question from Google and are looking about how to pass an array to routerLink; so this answer might help them.

consider this example:

<a [routerLink]="['news', newsId, newsTitle]">

the first item (news) is a text because it's inside quotation marks, and other two items are variables that might be inside a ngFor

Mohammad Kermani
  • 5,188
  • 7
  • 37
  • 61