Skip to content

Router navigateByUrl does not consistently apply queryParams #18798

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
jinder opened this issue Aug 20, 2017 · 28 comments
Closed

Router navigateByUrl does not consistently apply queryParams #18798

jinder opened this issue Aug 20, 2017 · 28 comments

Comments

@jinder
Copy link

jinder commented Aug 20, 2017

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[X] Bug report  
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question

Current behavior

In certain scenarios, navigateByUrl does not apply query params.

Expected behavior

It should always apply query params.

Minimal reproduction of the problem with instructions

Plunkr provided here: http://plnkr.co/edit/846in1yy0rjneOR5YbXD

Click the two buttons at the top to see the difference in behaviour.

What is the motivation / use case for changing the behavior?

Environment


Angular version: 4.3.5

Browser:
- [X] Chrome (desktop) version XX
- [ ] Chrome (Android) version XX
- [ ] Chrome (iOS) version XX
- [ ] Firefox version XX
- [ ] Safari (desktop) version XX
- [ ] Safari (iOS) version XX
- [ ] IE version XX
- [ ] Edge version XX
@jinder
Copy link
Author

jinder commented Sep 1, 2017

@vicb @jasonaden could you confirm if this is expected behaviour or not?

@johnny-mh
Copy link

johnny-mh commented Sep 11, 2017

same issue. navigateByUrl doesn't apply queryParams.

@kingkassem
Copy link

same issue

@soulfresh
Copy link

For me, this worked (maintained the query params in navigation events):

this.router.navigateByUrl(
  this.router.createUrlTree(
    ['some/route'], {queryParams: myParamObject}
  )
);

But this did not (navigation events did not contain the query param string):

this.router.navigateByUrl('some/route', {queryParams: myParamObject});

@jasonaden
Copy link
Contributor

This is an unfortunate issue with the documentation. The navigateByUrl command documentation says it will Navigate based on the provided url. This URL can be either a string or a UrlTree. What it doesn't say is it ignores most of the NavigationExtras. It only looks at skipLocationChange and replaceUrl, neither of which actually modify the URL.

The navigate command will operate on navigationExtras.queryParams to create a new URL tree, then internally calls navigateByUrl with that new URL Tree.

I've created a task to get this sorted out. Either by deprecating NavigationExtras and providing the correct API surface area, or at least clarifying in the documentation.

@schankam
Copy link

schankam commented Nov 12, 2018

I was having headache trying to figure out what was the problem, and this post save me a lots of time. But why the documentation is completely unclear and broken about this ??

@majaray
Copy link

majaray commented Nov 12, 2018

same issue here.
Any temp fix for this issue while we waiting the official fix?

@egyedia
Copy link

egyedia commented Nov 16, 2018

This post is great. It is a pity that the documentation was not fixed yet. I just lost ~1.5h trying to come up with very tricky workarounds. I need to work on my searching skills instead :)

@jasonHzq
Copy link

Is there any other method to navigate with a queryParams?

@vesrah
Copy link

vesrah commented Feb 7, 2019

Is there any other method to navigate with a queryParams?

router.navigate(['/path/here'], { queryParams: { k: v }})

@gund
Copy link

gund commented Feb 13, 2019

This is really confusing, I've spent 30 minutes on this to realise it is broken and not my fault...

Why navigationExtras still not deprecated, it is easy to do and this issue is open for 2 years already?...

@guidelli
Copy link

guidelli commented May 6, 2019

Same problem for me. I'm using angular 7.

@sam-s4s
Copy link

sam-s4s commented Aug 28, 2019

Oh wow, I'm in August 2019 and have just run into this problem. Still hasn't been fixed?
Why can't navigateByUrl just look at the NavigationExtras?

Also the documentation literally gives you an example doing this, which obviously won't work:

let navigationExtras: NavigationExtras = {
  queryParamsHandling: 'preserve',
  preserveFragment: true
};

// Redirect the user
this.router.navigateByUrl(redirect, navigationExtras);

What the heck??? A 2 year old problem that hasn't been fixed or documentation updated? Wastes half an hour of every developer's time when they run into this problem...

@cmunerap
Copy link

I have exactly the same issue at this moment with the tutorial @sam-s4s :

This doesn't work:

const navigationExtras: NavigationExtras = {
  queryParamsHandling: 'preserve',
  preserveFragment: true
};

// Redirect the user
this.router.navigateByUrl(redirect, navigationExtras);

This works as expected

const navigationExtras: NavigationExtras = {
  queryParamsHandling: 'preserve',
  preserveFragment: true
};

// Redirect the user
this.router.navigate(['admin'], navigationExtras);

https://angular.io/guide/router#query-parameters-and-fragments

@kl2426
Copy link

kl2426 commented Oct 25, 2019

什么情况?有其他解决办法吗

@speciesunknown
Copy link

This is a bit of a joke. I had to write my own. Bug it begs the question, whats the point of router.navigateByUrl if it doesnt support half the features of the full one?

@sam-s4s
Copy link

sam-s4s commented Nov 26, 2019

Yes, because of this bug, I was dropping query params and not even knowing until someone found the bug. Not good.

The only workaround seems to be to either use router.navigate , if you can, or use router.navigateByUrl but add your query params to the end of the url (in my case, I have to read them when the app loads, and then re-construct them and add them on the end when I want to navigatebyUrl).

This bug should never have existed, let alone been documented incorrectly, and then not fixed for literally years... seems to be getting ignored, too, sadly.

@TheParad0X
Copy link

This Bug cost me 4 hours :(

@odaper
Copy link

odaper commented Jan 12, 2020

I've encountered the same issue, I unfortunately used the route.navigate instead of route.navigateByUrl.
I'm using ngrx and routing via effects, I share with you my solution:

this.router.navigate([this.route.url,
       {
         outlets: {
           'call': [
             'product',
             'search',
           ]
         }
       }
     ],
     {
         queryParams: { userId: data.userId},
         relativeTo: this.activeRoute
     });

We can't with the last version of angular v8 send queryParams via navigateByUrl
I hope that it will be resolved soon

@danyrojj
Copy link

facing same issue with state param :/

@sebinbenjamin
Copy link

sebinbenjamin commented Jun 1, 2020

What's going on? Will this be fixed or is it already fixed?
Looks like this was fixed.

@dmkuba
Copy link

dmkuba commented Jun 6, 2020

Still reproduces. Signature of the function navigateByUrl allows us to pass query params (as second argument within extras object), but these params are ignored when navigation happened.

@speciesunknown
Copy link

What's going on? Will this be fixed or is it already fixed?
Looks like this was fixed.

It won't be. Its been a problem for 3 years and hasn't received any attention.

@atscott
Copy link
Contributor

atscott commented Jul 8, 2020

Lowering severity to "confusing" as the documentation does state that "The function ignores any properties in the NavigationExtras that would change the provided URL." This is working as intended, as described by Jason in this comment. The function signature could be improved further by not accepting the whole NavigationExtras type, but only the options that are actually used.

atscott added a commit to atscott/angular that referenced this issue Jul 24, 2020
…eUrlTree to be more accurate

`router.navigateByUrl` and `router.createUrlTree` only use a subset of the `NavigationExtras`. This commit
changes the parameter type to pick only those properties which are used in the implementations.

Fixes angular#18798
atscott added a commit to atscott/angular that referenced this issue Jul 24, 2020
…eUrlTree to be more accurate

`router.navigateByUrl` and `router.createUrlTree` only use a subset of the `NavigationExtras`. This commit
changes the parameter type to pick only those properties which are used in the implementations.

This change also avoids introducing a new type to limit the public API impact.

Lastly, this is a non-breaking change because only the input parameter
types are being changed, not any storage types. A complete `NavigationExtras` object still
conforms to the new parameter type.

Fixes angular#18798
atscott added a commit to atscott/angular that referenced this issue Jul 24, 2020
…eUrlTree to be more accurate

`router.navigateByUrl` and `router.createUrlTree` only use a subset of the `NavigationExtras`. This commit
changes the parameter type to pick only those properties which are used in the implementations.

This change also avoids introducing a new type to limit the public API impact.

Lastly, this is a non-breaking change because only the input parameter
types are being changed, not any storage types. A complete `NavigationExtras` object still
conforms to the new parameter type.

Fixes angular#18798
atscott added a commit to atscott/angular that referenced this issue Jul 24, 2020
…eUrlTree to be more accurate

`router.navigateByUrl` and `router.createUrlTree` only use a subset of the `NavigationExtras`. This commit
changes the parameter type to pick only those properties which are used in the implementations.

This change also avoids introducing a new type to limit the public API impact.

Fixes angular#18798

BREAKING CHANGE: While the new parameter types allow a variable of type
`NavigationExtras` to be passed in, they will not allow object literals,
as they may only specify known properties. They will also not accept
types that do not have properties in common with the ones in the `Pick`.
To fix this error, only specify properties from the `NavigationExtras` which are
actually used in the respective function calls.
atscott added a commit to atscott/angular that referenced this issue Jul 24, 2020
…eUrlTree to be more accurate

`router.navigateByUrl` and `router.createUrlTree` only use a subset of the `NavigationExtras`. This commit
changes the parameter type to pick only those properties which are used in the implementations.

This change also avoids introducing a new type to limit the public API impact.

Fixes angular#18798

BREAKING CHANGE: While the new parameter types allow a variable of type
`NavigationExtras` to be passed in, they will not allow object literals,
as they may only specify known properties. They will also not accept
types that do not have properties in common with the ones in the `Pick`.
To fix this error, only specify properties from the `NavigationExtras` which are
actually used in the respective function calls or use a type assertion
on the object or variable: `as NavigationExtras`.
@codemile
Copy link

codemile commented Aug 13, 2020

I hope someone on the Angular team receives a notification for this comment, navigates to this issue from their email, scrolls all the way down to the bottom past all the previous comments, and finds that I'm just here to complain that I wasted almost an hour trying to figure out why my code isn't working as documented.

Here that person would think. "Darn... I just wasted my time reading this person's comment".

See.. that's what it feels like.

@SchnWalter
Copy link
Contributor

I've completely forgot that I've ran into this issue some time ago and I've ended up wasting a good amount of time debugging the router, for a 2nd time.

For those that really want to use queryParams with navigateByUrl(), here's an example service:

import { NavigationExtras as CoreNavigationExtras, Router, UrlTree } from '@angular/router';
import { trim } from 'lodash';

/**
 * A list of NavigationExtras options that are used by Router.navigateByUrl() with added support for queryParams.
 *
 * @see https://github.com/angular/angular/pull/38227
 */
export type MyNavigationExtras = Pick<CoreNavigationExtras, 'skipLocationChange'|'replaceUrl'|'state'|'queryParams'>;

export class MyNavigationService {
  constructor(private readonly router: Router) { }

  /**
   * Navigates to a view using an absolute route path, with support for query parameters.
   *
   * @see https://angular.io/api/router/NavigationExtras
   * @see https://github.com/angular/angular/issues/18798
   */
  public navigateByUrl(url: string | UrlTree, extras?: MyNavigationExtras): Promise<boolean> {
    if (extras?.queryParams) {
      const updatedExtras: CoreNavigationExtras = {
        ...extras,
        relativeTo: this.router.routerState.root
      };
      const urlString: string = url instanceof UrlTree ? this.router.serializeUrl(url) : url;
      const urlCommands: string[] = trim(urlString, '/').split('/');
      return this.router.navigate(urlCommands, updatedExtras);
    }
    return this.router.navigateByUrl(url, extras);
  }
}

atscott added a commit to atscott/angular that referenced this issue Sep 17, 2020
…eUrlTree to be more accurate

`router.navigateByUrl` and `router.createUrlTree` only use a subset of the `NavigationExtras`. This commit
changes the parameter type to pick only those properties which are used in the implementations.

This change also avoids introducing a new type to limit the public API impact.

Fixes angular#18798

BREAKING CHANGE: While the new parameter types allow a variable of type
`NavigationExtras` to be passed in, they will not allow object literals,
as they may only specify known properties. They will also not accept
types that do not have properties in common with the ones in the `Pick`.
To fix this error, only specify properties from the `NavigationExtras` which are
actually used in the respective function calls or use a type assertion
on the object or variable: `as NavigationExtras`.
atscott added a commit to atscott/angular that referenced this issue Sep 22, 2020
…eUrlTree to be more accurate

`router.navigateByUrl` and `router.createUrlTree` only use a subset of the `NavigationExtras`. This commit
changes the parameter type to use new interfaces that only specify the properties used by
those function implementations. `NavigationExtras` extends both of those interfaces.

Fixes angular#18798

BREAKING CHANGE: While the new parameter types allow a variable of type
`NavigationExtras` to be passed in, they will not allow object literals,
as they may only specify known properties. They will also not accept
types that do not have properties in common with the ones in the `Pick`.
To fix this error, only specify properties from the `NavigationExtras` which are
actually used in the respective function calls or use a type assertion
on the object or variable: `as NavigationExtras`.
@guy-roberts
Copy link

Yep, it took me over an hour to get here, after first following the example in the doc.

@alxhub alxhub closed this as completed in e4f4d18 Sep 25, 2020
@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Oct 26, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.