Angular.js: $location.hash inserts two hash signs

Created on 21 Jan 2016  路  10Comments  路  Source: angular/angular.js

When on the url index.html when I set the hash at some point to, say, "foo=bar", the url gets two hashes in it.

So, as part of a click handler or something (doesn't really matter):

$location.hash("foo=bar");

The url becomes:

index.html##foo=bar

But we should expect:

index.html#foo=bar

This is Angular 1.4.8 on Firefox 43 on Windows 10.
Also happens in Chrome 47, IE11, and Edge 13.

$location

Most helpful comment

Yes, I've literally just stumbled on this too.

It breaks the Yeoman generated project that I just created, which had all the same settings as one made only fairly recently (but presumably that will have been before the BC went out)

You're probably all much better devs than me :smile: , but for anyone else who stumbles on this and simply wants to undo the BC, it's just a matter of putting this in the .config:

```javascript
.config(function ($routeProvider, $locationProvider) {
...
// undo the default ('!')
$locationProvider.hashPrefix('');
});

All 10 comments

You can use

var url = $location.absUrl();

This is due to the fact that the default location mode is html5Mode(false), which relies upon using hash-bang style paths. Unfortunately the default hash-prefix is nothing "" and so we the location service adds in the hash-bang path (i.e. #) followed by your hash, #foo=bar.

The simple workarounds are:

  • turn on HTML5 mode: $locationProvider.html5Mode(true)
  • set a hashPrefix: $locationProvider.hashPrefix('!'), which will result in urls that look like: index.html#!#foo=bar

The differences between html5 and hashbang mode are detailed in the dev guide (in case you haven't read that already).

This pretty much expected behavior.
Are you using client-side routing (e.g. ngRoute or uiRouter) ?

@gkalpak - do you think we ought to make a BC in 1.5.0 and change the default hashPrefix to be "!"? This would make this less confusing IMO.

@gkalpak I'm not using any type of routing. It's a true singlepage application I'm working on, that just needs to store a search query in the url.

@petebacondarwin Would html5Mode not cause the hash sign to disappear completely? html5Mode usually requires changes at the server level (rewriting urls and stuff) which in our case is not an option... The hashPrefix isn't a real elegant workaround, I hope you agree. I would like to keep the url as elegant as I can with the restriction I mentioned.

If you are not doing routing and you never change the $location.path() then you don't need any server side support. It will only get rid of the first hash. I would give it a try.

@thany:

It's a true singlepage application I'm working on

_true singlepage applications_ do have client-side routing (unless you mean it's just a single page :smiley:).

just needs to store a search query in the url

Why are you using .hash() if you want too store a search query ? (Or do you also need the hash in addition to the search query ?)

html5Mode usually requires changes at the server level

If there is indeed no client-side routing involved, then html5 should not need any configuration on the server.

Would html5Mode not cause the hash sign to disappear completely

It would make the 1st hash disappear, not both of them.
BTW, if (let me say it again) there is no client-side routing involved, you could get away with using .path() for setting the hash without the need to turn on html5 mode (but it's more of a hack, than a real solution).

@petebacondarwin: It would have made sense for ! to be the default hashPrefix from the beginning. At this point I am not sure the benefits warrant the BC. Could go either way, but I slighlty lean towards leaving it as is.

All our routes now have !# which has broken some links. I take it this is a breaking change?

Yes, I've literally just stumbled on this too.

It breaks the Yeoman generated project that I just created, which had all the same settings as one made only fairly recently (but presumably that will have been before the BC went out)

You're probably all much better devs than me :smile: , but for anyone else who stumbles on this and simply wants to undo the BC, it's just a matter of putting this in the .config:

```javascript
.config(function ($routeProvider, $locationProvider) {
...
// undo the default ('!')
$locationProvider.hashPrefix('');
});

Was this page helpful?
0 / 5 - 0 ratings