Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

$location.hash inserts two hash signs #13812

Closed
thany opened this issue Jan 21, 2016 · 10 comments
Closed

$location.hash inserts two hash signs #13812

thany opened this issue Jan 21, 2016 · 10 comments
Assignees
Milestone

Comments

@thany
Copy link

thany commented Jan 21, 2016

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.

@thany thany changed the title $location.hash insert two hash signs $location.hash insertd two hash signs Jan 21, 2016
@thany thany changed the title $location.hash insertd two hash signs $location.hash inserts two hash signs Jan 21, 2016
@gabrielclima
Copy link

You can use

var url = $location.absUrl();

@petebacondarwin
Copy link
Contributor

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

@gkalpak
Copy link
Member

gkalpak commented Jan 22, 2016

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) ?

@petebacondarwin
Copy link
Contributor

@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.

@thany
Copy link
Author

thany commented Jan 22, 2016

@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.

@petebacondarwin
Copy link
Contributor

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.

@gkalpak
Copy link
Member

gkalpak commented Jan 22, 2016

@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 😃).

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.

petebacondarwin added a commit to petebacondarwin/angular.js that referenced this issue Mar 9, 2016
The $location service is designed to support hash prefixed URLs
for cases where the browser does not support HTML5 push-state navigation.

The Google Ajax Crawling Scheme expects that local paths within a SPA start
with a hash-bang (e.g. `somedomain.com/base/path/#!/client/side/path`).

The `$locationProvide` allows the application developer to configure the
hashPrefix, and it is normal to set this to a bang '!', but the default
has always been the empty string ''.

This has caused some confusion where a user is not aware of this feature
and wonders why adding a hash value to the location (e.g. `$location.hash('xxx')`)
results in a double hash: `##xxx`.

This commit changes the default value of the prefix to '!', which is more
natural and expected.

See https://developers.google.com/webmasters/ajax-crawling/docs/getting-started

Closes angular#13812

BREAKING CHANGE

The hash-prefix for `$location` hash-bang URLs has changed from the empty
string "" to the bang "!". If your application does not use HTML5 mode
or is being run on browsers that do not support HTML5 mode, and you have
not specified your own hash-prefix then client side URLs will now contain
a "!" prefix. For example, rather than `mydomain.com/#/a/b/c` will become
`mydomain/#!/a/b/c`.

If you actually wanted to have no hash-prefix then you should configure
this by adding a configuration block to you application:

```
appModule.config(['$locationProvider', function($locationProvider) {
  $locationProvider.hashPrefix("");
}]);
```
petebacondarwin added a commit to petebacondarwin/angular.js that referenced this issue Mar 9, 2016
The $location service is designed to support hash prefixed URLs
for cases where the browser does not support HTML5 push-state navigation.

The Google Ajax Crawling Scheme expects that local paths within a SPA start
with a hash-bang (e.g. `somedomain.com/base/path/#!/client/side/path`).

The `$locationProvide` allows the application developer to configure the
hashPrefix, and it is normal to set this to a bang '!', but the default
has always been the empty string ''.

This has caused some confusion where a user is not aware of this feature
and wonders why adding a hash value to the location (e.g. `$location.hash('xxx')`)
results in a double hash: `##xxx`.

This commit changes the default value of the prefix to '!', which is more
natural and expected.

See https://developers.google.com/webmasters/ajax-crawling/docs/getting-started

Closes angular#13812

BREAKING CHANGE

The hash-prefix for `$location` hash-bang URLs has changed from the empty
string "" to the bang "!". If your application does not use HTML5 mode
or is being run on browsers that do not support HTML5 mode, and you have
not specified your own hash-prefix then client side URLs will now contain
a "!" prefix. For example, rather than `mydomain.com/#/a/b/c` will become
`mydomain/#!/a/b/c`.

If you actually wanted to have no hash-prefix then you should configure
this by adding a configuration block to you application:

```
appModule.config(['$locationProvider', function($locationProvider) {
  $locationProvider.hashPrefix("");
}]);
```
petebacondarwin added a commit to petebacondarwin/angular.js that referenced this issue Mar 9, 2016
The $location service is designed to support hash prefixed URLs
for cases where the browser does not support HTML5 push-state navigation.

The Google Ajax Crawling Scheme expects that local paths within a SPA start
with a hash-bang (e.g. `somedomain.com/base/path/#!/client/side/path`).

The `$locationProvide` allows the application developer to configure the
hashPrefix, and it is normal to set this to a bang '!', but the default
has always been the empty string ''.

This has caused some confusion where a user is not aware of this feature
and wonders why adding a hash value to the location (e.g. `$location.hash('xxx')`)
results in a double hash: `##xxx`.

This commit changes the default value of the prefix to '!', which is more
natural and expected.

See https://developers.google.com/webmasters/ajax-crawling/docs/getting-started

Closes angular#13812

BREAKING CHANGE

The hash-prefix for `$location` hash-bang URLs has changed from the empty
string "" to the bang "!". If your application does not use HTML5 mode
or is being run on browsers that do not support HTML5 mode, and you have
not specified your own hash-prefix then client side URLs will now contain
a "!" prefix. For example, rather than `mydomain.com/#/a/b/c` will become
`mydomain/#!/a/b/c`.

If you actually wanted to have no hash-prefix then you should configure
this by adding a configuration block to you application:

```
appModule.config(['$locationProvider', function($locationProvider) {
  $locationProvider.hashPrefix("");
}]);
```
petebacondarwin added a commit to petebacondarwin/angular.js that referenced this issue Mar 21, 2016
The $location service is designed to support hash prefixed URLs
for cases where the browser does not support HTML5 push-state navigation.

The Google Ajax Crawling Scheme expects that local paths within a SPA start
with a hash-bang (e.g. `somedomain.com/base/path/#!/client/side/path`).

The `$locationProvide` allows the application developer to configure the
hashPrefix, and it is normal to set this to a bang '!', but the default
has always been the empty string ''.

This has caused some confusion where a user is not aware of this feature
and wonders why adding a hash value to the location (e.g. `$location.hash('xxx')`)
results in a double hash: `##xxx`.

This commit changes the default value of the prefix to '!', which is more
natural and expected.

See https://developers.google.com/webmasters/ajax-crawling/docs/getting-started

Closes angular#13812

BREAKING CHANGE

The hash-prefix for `$location` hash-bang URLs has changed from the empty
string "" to the bang "!". If your application does not use HTML5 mode
or is being run on browsers that do not support HTML5 mode, and you have
not specified your own hash-prefix then client side URLs will now contain
a "!" prefix. For example, rather than `mydomain.com/#/a/b/c` will become
`mydomain/#!/a/b/c`.

If you actually wanted to have no hash-prefix then you should configure
this by adding a configuration block to you application:

```
appModule.config(['$locationProvider', function($locationProvider) {
  $locationProvider.hashPrefix("");
}]);
```
@steveharan
Copy link

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

@nmstoker
Copy link

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 😄 , 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:

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

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.

6 participants