141

My AngularJS application needs to have access to the user's LinkedIn profile. In order to do that I need to redirect the user to a LinkedIn URL which contains a callback redirect_uri parameter which will tell LinkedIn to redirect the user back to my webapp and include a "code" query param in the URL. It's a traditional Oauth 2.0 flow.

Everything works great except that LinkedIn redirects the user back to the following URL:

http://localhost:8080/?code=XXX&state=YYY#/users/123/providers/LinkedIn/social-sites

I would like to remove ?code=XXX&state=YYY from the URL in order to make it clean. The user does not need to see the query parameters I received from LinkedIn redirect.

I tried $location.absUrl($location.path() + $location.hash()).replace(), but it keep the query params in the URL.

I am also unable to extract the query parameters, e.g. "code", using ($location.search()).code. It seems like having ? before # in the URL above is tricking Angular.

alecswan
  • 3,670
  • 5
  • 25
  • 35

15 Answers15

157

I use

$location.search('key', null)

As this not only deletes my key but removes it from the visibility on the URL.

Julius
  • 2,473
  • 3
  • 20
  • 26
  • 2
    this causes a back button loop in chrome as in the back button goes back to //example.com?key=value, but angular forwards to //example.com. Suggestions? – jaybro Aug 31 '15 at 14:34
  • 2
    This sounds a bit like code issue to me. Angular should not forward anything, unless there's some king of method added by you. Also, adding .replace() replaces current history entry. – Julius Sep 01 '15 at 15:42
  • viewModelHelper.navigateTo('foo/'); was persisting the query string to the foo url, so i fixed it by using window.location.href = 'foo/'; instead. – jaybro Sep 02 '15 at 18:33
  • 2
    Do not use window, use Angular's $window instead. It will be easier to unit test. More: https://docs.angularjs.org/api/ng/service/$window – Julius Sep 03 '15 at 20:23
  • This anwers works perfect if you want to delete an especific param, thanks. – Dexxo Nov 04 '16 at 21:59
  • This is much better as it is not accessing private variables. The way Angular is intended. – Ben Taliadoros Nov 24 '16 at 11:08
  • @Julius or alternatively, you could expect your developers to know the bare minimum about how javascript works and not copy paste crap internet code into your project. That is my preferred method for making sure window doesn't get overridden.... $window as a service is a prime example of overly complicating something very simple in a useless and annoying way. – Kyle Zimmer Oct 22 '20 at 00:02
110

I ended up getting the answer from AngularJS forum. See this thread for details


The link is to a Google Groups thread, which is difficult to read and doesn't provide a clear answer. To remove URL parameters use

$location.url($location.path());
jnrcorp
  • 1,905
  • 1
  • 18
  • 25
alecswan
  • 3,670
  • 5
  • 25
  • 35
  • 1
    I think you meant to put the path in $location.url() instead of $location.path. Trying to merge them both like above does not work for me. – mbdev Jan 07 '14 at 05:41
  • 1
    does not work for me too. Both functions leave the query param there. – Pablo Ezequiel Leone Sep 10 '14 at 08:32
  • helpful answer indeed. In my scenario, each time after the first time I had trigger $location.path('/reportmaint').search({ }), it never cleaned out the previous query parameters. – bob.mazzo Oct 06 '14 at 17:51
  • this causes a back button loop in chrome as in the back button goes back to //example.com?key=value, but angular forwards to //example.com. Suggestions? – jaybro Aug 31 '15 at 14:38
  • 1
    +1 for `The link is to a Google Groups thread, which is difficult to read and doesn't provide a clear answer` – Vlad Feb 17 '17 at 12:07
80

To remove ALL query parameters, do:

$location.search({});

To remove ONE particular query parameter, do:

$location.search('myQueryParam', null);
Rahul Desai
  • 15,242
  • 19
  • 83
  • 138
29

To clear an item delete it and call $$compose

    if ($location.$$search.yourKey) {
        delete $location.$$search.yourKey;
        $location.$$compose();
    }

derived from angularjs source : https://github.com/angular/angular.js/blob/c77b2bcca36cf199478b8fb651972a1f650f646b/src/ng/location.js#L419-L443

basarat
  • 261,912
  • 58
  • 460
  • 511
  • 2
    brilliant! Worked like a charm. – paulcpederson May 23 '14 at 21:26
  • This worked for me, but I would assume Julius' solution is more correct, as it seems to be what Angular guys had in mind when they created the `search` method. https://docs.angularjs.org/api/ng/service/$location#search – zmilojko Jan 23 '15 at 19:00
  • 2
    Thanks, this worked quite well... Interestingly, IE8 likes to set/compose that URL and then load it subsequently. I'm sure this is why proper routing is preferred and also why we are all bad people. :P – RomoCode Feb 16 '15 at 02:36
  • Also keep in mind that any methods/variables prefixed with `$$` are *not* considered PUBLIC APIs in AngularJS—and therefore can be subject to change/break from release to release without notice. While AngularJS is now in LTS mode and unlikely to receive anything but security patches in the near future, it's still a good reason in general to avoid using these interfaces wherever possible, because they're considered "internal" implementation details. – runderworld Apr 28 '21 at 19:03
27

You can delete a specific query parameter by using:

delete $location.$$search.nameOfParameter;

Or you can clear all the query params by setting search to an empty object:

$location.$$search = {};
Quintin
  • 295
  • 3
  • 5
  • 2
    I don't know why, but this solution doesn't work well while switching over pages (the parameters can reappear, even if `$location.$$search = {}` is executed). @basarat solution is working well. – Mik378 Jun 02 '14 at 10:59
  • 1
    Worked fine for me - maybe check the sequence in which you are removing the parameter and changing path? – demaniak Jul 15 '14 at 15:07
  • 1
    Although this may work it accesses private variables which shouldn't be modified, see @Julius answer for another solution – Ben Taliadoros Nov 24 '16 at 11:10
27

At the time of writing, and as previously mentioned by @Bosh, html5mode must be true in order to be able to set $location.search() and have it be reflected back into the window’s visual URL.

See https://github.com/angular/angular.js/issues/1521 for more info.

But if html5mode is true you can easily clear the URL’s query string with:

$location.search('');

or

$location.search({});

This will also alter the window’s visual URL.

(Tested in AngularJS version 1.3.0-rc.1 with html5Mode(true).)

Fredric
  • 1,223
  • 18
  • 16
12

Need to make it work when html5mode = false?

All of the other answers work only when Angular's html5mode is true. If you're working outside of html5mode, then $location refers only to the "fake" location that lives in your hash -- and so $location.search can't see/edit/fix the actual page's search params.

Here's a workaround, to be inserted in the HTML of the page before angular loads:

<script>
  if (window.location.search.match("code=")){
    var newHash = "/after-auth" + window.location.search;
    if (window.history.replaceState){
      window.history.replaceState( {}, "", window.location.toString().replace(window.location.search, ""));
    }
    window.location.hash = newHash;
  }
</script>
Bosh
  • 8,138
  • 11
  • 51
  • 77
  • 2
    Another way I avoided configuring html5Mode to true is by creating the query string such that it contains the **#** right before the **?**. so have `myapp/#?client=clientName` instead of `myapp/?client=clientName` – Angel Gao Feb 20 '15 at 21:44
6

If you want to move to another URL and clear the query parameters just use:

$location.path('/my/path').search({});
felippe
  • 493
  • 6
  • 7
5

Just use

$location.url();

Instead of

$location.path();
kevinius
  • 4,232
  • 7
  • 48
  • 79
1

If you are using routes parameters just clear $routeParams

$routeParams= null;
Oswaldo Alvarez
  • 4,772
  • 1
  • 22
  • 20
  • 1
    This will just set the local variable `$routeParams` to `null`. Won't actually affect the URL parameters in the address bar at all. – Eric Ferreira Jun 16 '16 at 15:29
1

How about just setting the location hash to null

$location.hash(null);
Bwyss
  • 1,736
  • 3
  • 25
  • 48
0

if you process the parameters immediately and then move to the next page, you can put a question mark on the end of the new location.

for example, if you would have done $location.path('/nextPage');

you can do this instead: $location.path('/nextPage?');

0

I've tried the above answers but could not get them to work. The only code that worked for me was $window.location.search = ''

Gwen Au
  • 859
  • 9
  • 10
0

I can replace all query parameters with this single line: $location.search({});
Easy to understand and easy way to clear them out.

0

The accepted answer worked for me, but I needed to dig a little deeper to fix the problems with the back button.

What I noticed is that if I link to a page using <a ui-sref="page({x: 1})">, then remove the query string using $location.search('x', null), I don't get an extra entry in my browser history, so the back button takes me back to where I started. Although I feel like this is wrong because I don't think that Angular should automatically remove this history entry for me, this is actually the desired behaviour for my particular use-case.

The problem is that if I link to the page using <a href="/page/?x=1"> instead, then remove the query string in the same way, I do get an extra entry in my browser history, so I have to click the back button twice to get back to where I started. This is inconsistent behaviour, but actually this seems more correct.

I can easily fix the problem with href links by using $location.search('x', null).replace(), but then this breaks the page when you land on it via a ui-sref link, so this is no good.

After a lot of fiddling around, this is the fix I came up with:

In my app's run function I added this:

$rootScope.$on('$locationChangeSuccess', function () {
    $rootScope.locationPath = $location.path();
});

Then I use this code to remove the query string parameter:

$location.search('x', null);

if ($location.path() === $rootScope.locationPath) {
    $location.replace();
}
Moo
  • 849
  • 7
  • 16