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

Back button does not work when using html5Mode without <base> tag #14959

Closed
onlywei opened this issue Jul 27, 2016 · 8 comments
Closed

Back button does not work when using html5Mode without <base> tag #14959

onlywei opened this issue Jul 27, 2016 · 8 comments

Comments

@onlywei
Copy link
Contributor

onlywei commented Jul 27, 2016

Note: for support questions, please use one of these channels: https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md#question. This repository's issues are reserved for feature requests and bug reports.

Do you want to request a feature or report a bug?
Bug

What is the current behavior?
This is a little difficult to explain so bear with me. To get to this point, a number of workarounds of existing limitations were used:

  1. $locationProvider.html5Mode({enabled: true, requireBase: false}) is turned on. Base tag is avoided in order for <svg> icons with xlink:href to be used.
  2. Since there is no base tag, in order to actually leave the SPA and go to another page on the same server, we have to manually call location.reload() when a URL that does not belong to our routers configured routes is detected.
  3. After location.reload(), the new page loads as expected, but the back button does not work. It changes the URL, but the browser never asks the server for a page refresh.

If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem via https://plnkr.co or similar

http://plnkr.co/edit/LyCi3ikziOttlI7lZfCv?p=preview

To see the problem, open the plnkr demo, Read through the code a bit, and then click the link to bring you to the html5mode page. In that page, you should see another link that will bring you back to first page. Then, click the back button in your browser. It should not work!

What is the expected behavior?
I expect the browser to completely forget that Angular ever did anything to its URL change behavior when I load a new page via location.reload(). When I load the 2nd destination page, it may be an Angular page, or it may not be. In both cases the back button should take me back to the original html5mode angular page.

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

Which versions of Angular, and which browser / OS are affected by this issue? Did this work in previous versions of Angular? Please also test with the latest stable and snapshot (https://code.angularjs.org/snapshot/) versions.
1.5.6, 1.5.7 - did not test older versions

Other information (e.g. stacktraces, related issues, suggestions how to fix)
I have noticed that if I inject $location into the page that I expect to press the back button in, it works! But, I don't want to have to inject $location into that page for no reason other than to fix this.

@gkalpak
Copy link
Member

gkalpak commented Jul 28, 2016

I think this is "expected behavior", based on how history.pushState/back work and the fact that you are configuring Angular to use history (that's what it does in HTML5 mode) and finally the fact you use no base tag (essentially preventing Angular from being able to distinguish links that lead to external pages from links that lead to a new view inside the app).

You can see what is going on under the hood in this plnkr, which emulates your configuration, but without Angular.

This post might shed some light on how history.pushState works.

You can avoid this, by disabling the URL-rewriting functionality (enabled by default) on your second page: updated plnkr

If you don't want to disable URL-rewriting for all links, you can disable it on specific links only, by using target="_self" on those links (which automatically disables URL-rewriting): another plnkr

Or you could handle the popstate/hashchange events yourself (e.g. calling location.reload() when appropriate).

Alternatively, (as you have already found out) you can let Angular handle all of this, by instantiating $location on your first page 😃

@onlywei
Copy link
Contributor Author

onlywei commented Jul 28, 2016

@gkalpak This is an amazing answer, thank you! Setting rewriteLinks: false did the trick for us. It's great!

@onlywei
Copy link
Contributor Author

onlywei commented Jul 28, 2016

Also @gkalpak would it be possible to opt-in to rewriting links on a link per link basis? If I set rewriteLinks: false globally, but then I want some specific links on my page not to do so, can I do something like:

<a href="some/internal/path" ng-href-rewrite="true">

?

I believe this should be a simple add based on what I read inside the location.js source code.

@gkalpak
Copy link
Member

gkalpak commented Jul 29, 2016

No, it is not possible currently. It would indeed be a simple change I believe (but I am not sure it is necessary). Feel free to open a feature request about that or better yet submit a pull request to kick of the discussion.

I am going to close this, since the current behavior is expected (afaict 😛) and you were able to work things out.

Ooc, can you post an example showing why you can't have a <base> tag?

@gkalpak gkalpak closed this as completed Jul 29, 2016
@onlywei
Copy link
Contributor Author

onlywei commented Jul 29, 2016

@gkalpak Here's an example of why I can't use <base> tag: http://www.wei-wang.com/base_svg/
I wasn't able to get it to work in plunkr. You can see all my code in your dev tools inspector.

onlywei pushed a commit to onlywei/angular.js that referenced this issue Aug 1, 2016
See this discussion: angular#14959

When using html5mode, sometimes it is necessary to not use the <base> tag
in order to support SVG icons. An example of this is in the discussion
linked above.

When we do this, sometimes we also want to disable "rewriteLinks" so that
we can still leave the Angular application via navigation.

This feature allows the user to explicitly mark an <a> tag as a link that
should not refresh from server, even if rewriteLinks is disabled.
@gkalpak
Copy link
Member

gkalpak commented Aug 5, 2016

@onlywei, I can't reproduce the problem. Does it happen on specific browsers only?

@onlywei
Copy link
Contributor Author

onlywei commented Aug 5, 2016

@gkalpak It happens to me on Chrome, Firefox, and Edge. Try playing with the URL - remove the query params and hit enter, then refresh. I've changed the text in the example to have more generic instructions on how to see the problem.

onlywei pushed a commit to onlywei/angular.js that referenced this issue Aug 5, 2016
See this discussion: angular#14959

When using html5mode, sometimes it is necessary to not use the <base> tag
in order to support SVG icons. An example of this is in the discussion
linked above.

When we do this, sometimes we also want to disable "rewriteLinks" so that
we can still leave the Angular application via navigation.

This feature allows the user to explicitly mark an <a> tag as a link that
should not refresh from server, even if rewriteLinks is disabled.
@gkalpak
Copy link
Member

gkalpak commented Aug 7, 2016

@onlywei, I see it now. It seems to me like a bug/weirdness in the way <use> elements' href works in the presense of a <base> tag and a URL with query params. (Either that or my lack of SVG knowledge 😃)

onlywei pushed a commit to onlywei/angular.js that referenced this issue Aug 7, 2016
See this discussion: angular#14959

When using html5mode, sometimes it is necessary to not use the <base> tag
in order to support SVG icons. An example of this is in the discussion
linked above.

When we do this, sometimes we also want to disable "rewriteLinks" so that
we can still leave the Angular application via navigation.

This feature allows the user to explicitly mark an <a> tag as a link that
should not refresh from server, even if rewriteLinks is disabled.
onlywei pushed a commit to onlywei/angular.js that referenced this issue Aug 7, 2016
See this discussion: angular#14959

When using html5mode, sometimes it is necessary to not use the <base> tag
in order to support SVG icons. An example of this is in the discussion
linked above.

When we do this, sometimes we also want to disable "rewriteLinks" so that
we can still leave the Angular application via navigation.

This feature allows the user to explicitly mark an <a> tag as a link that
should not refresh from server, even if rewriteLinks is disabled.
gkalpak pushed a commit that referenced this issue Aug 22, 2016
… attribute

In HTML5 mode, links can now be selectively rewritten, by setting `mode.rewriteLinks` to a string
(denoting an attribute name). Anchor elements that have the specified attribute will be rewritten,
while other links will remain untouched.

This can be useful in situations where it is desirable to use HTML5 mode without a `<base>` tag, but
still support rewriting specific links only. See #14959 for more details on a possible usecase.

Closes #14976
gkalpak pushed a commit that referenced this issue Aug 22, 2016
… attribute

In HTML5 mode, links can now be selectively rewritten, by setting `mode.rewriteLinks` to a string
(denoting an attribute name). Anchor elements that have the specified attribute will be rewritten,
while other links will remain untouched.

This can be useful in situations where it is desirable to use HTML5 mode without a `<base>` tag, but
still support rewriting specific links only. See #14959 for more details on a possible usecase.

Closes #14976
petebacondarwin pushed a commit to petebacondarwin/angular.js that referenced this issue Nov 21, 2016
… attribute

In HTML5 mode, links can now be selectively rewritten, by setting `mode.rewriteLinks` to a string
(denoting an attribute name). Anchor elements that have the specified attribute will be rewritten,
while other links will remain untouched.

This can be useful in situations where it is desirable to use HTML5 mode without a `<base>` tag, but
still support rewriting specific links only. See angular#14959 for more details on a possible usecase.

Closes angular#14976
petebacondarwin pushed a commit to petebacondarwin/angular.js that referenced this issue Nov 21, 2016
… attribute

In HTML5 mode, links can now be selectively rewritten, by setting `mode.rewriteLinks` to a string
(denoting an attribute name). Anchor elements that have the specified attribute will be rewritten,
while other links will remain untouched.

This can be useful in situations where it is desirable to use HTML5 mode without a `<base>` tag, but
still support rewriting specific links only. See angular#14959 for more details on a possible usecase.

Closes angular#14976
petebacondarwin pushed a commit to petebacondarwin/angular.js that referenced this issue Nov 21, 2016
… attribute

In HTML5 mode, links can now be selectively rewritten, by setting `mode.rewriteLinks` to a string
(denoting an attribute name). Anchor elements that have the specified attribute will be rewritten,
while other links will remain untouched.

This can be useful in situations where it is desirable to use HTML5 mode without a `<base>` tag, but
still support rewriting specific links only. See angular#14959 for more details on a possible usecase.

Closes angular#14976
petebacondarwin pushed a commit to petebacondarwin/angular.js that referenced this issue Nov 21, 2016
… attribute

In HTML5 mode, links can now be selectively rewritten, by setting `mode.rewriteLinks` to a string
(denoting an attribute name). Anchor elements that have the specified attribute will be rewritten,
while other links will remain untouched.

This can be useful in situations where it is desirable to use HTML5 mode without a `<base>` tag, but
still support rewriting specific links only. See angular#14959 for more details on a possible usecase.

Closes angular#14976
petebacondarwin pushed a commit to petebacondarwin/angular.js that referenced this issue Nov 21, 2016
… attribute

In HTML5 mode, links can now be selectively rewritten, by setting `mode.rewriteLinks` to a string
(denoting an attribute name). Anchor elements that have the specified attribute will be rewritten,
while other links will remain untouched.

This can be useful in situations where it is desirable to use HTML5 mode without a `<base>` tag, but
still support rewriting specific links only. See angular#14959 for more details on a possible usecase.

Closes angular#14976
petebacondarwin pushed a commit that referenced this issue Nov 23, 2016
… attribute

In HTML5 mode, links can now be selectively rewritten, by setting `mode.rewriteLinks` to a string
(denoting an attribute name). Anchor elements that have the specified attribute will be rewritten,
while other links will remain untouched.

This can be useful in situations where it is desirable to use HTML5 mode without a `<base>` tag, but
still support rewriting specific links only. See #14959 for more details on a possible usecase.

Closes #14976
petebacondarwin pushed a commit that referenced this issue Nov 24, 2016
… attribute

In HTML5 mode, links can now be selectively rewritten, by setting `mode.rewriteLinks` to a string
(denoting an attribute name). Anchor elements that have the specified attribute will be rewritten,
while other links will remain untouched.

This can be useful in situations where it is desirable to use HTML5 mode without a `<base>` tag, but
still support rewriting specific links only. See #14959 for more details on a possible usecase.

Closes #14976
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants