when I want to navigate to elements within an html, i use anchor with href="#id" directly which is the html standard, however angular's routing table does not contain this one, and regarda it as something not found. When interceptor is there, it will go to otherwise for 404 page. I have attached an example in plnkr here.
http://plnkr.co/edit/5KoWi1RFJOpRjc5rPwhO?p=preview
I don't think this is unexpected. Angular recognizes #
-prefixed paths as Angular paths (by default) and tries to route appropriately.
If you want to be able to scroll to element using anchors, you should change the hash-prefix, so Angular won't recognize #h1
as an Angular path:
.config(function ($locationProvider) {
$locationProvider.hashPrefix('!');
}
Then:
<a href="#h1">Scroll to element `#h1`</a>
<a href="#!h1">Navigate to route `h1`</a>
(Demo 1)
Alternatively, you can keep your current setup, but use the current path (as well as the hash) in anchors that should scroll to elements (not navigate to another route):
<a href="#some-route#h1">Scroll to element `#h1` in route 'some-route'</a>
<a href="#h1">Navigate to route `h1`</a>
(Demo 2)
Finally, you can setup a function in your controller that uses $location
's hash()
method to set the hash (in a way that lets Angular know it is a hash and not a path):
.controller('appCtrl', function ($location, $scope) {
$scope.scrollTo = function (hash) {
$location.hash(hash);
};
})
Then:
<a href="" ng-click="scrollTo('h1')>Scroll to element `#h1`</a>
<a href="#h1">Navigate to route `h1`</a>
(Demo 3)
@gkalpak Actually I use a lot third party libraries, and href="#id" is used a lot there. I think your demo explain that very well. Probably I need to use Demo1 to mitigate the 3rd party issues
@bargitta you have to add target="_self"
@lgalfaso: I don't really see how adding target="_self"
would help with this one: http://plnkr.co/edit/7DAYLjufAg30cZ625jU2?p=preview
Maybe I misunderstood the issue, the 404 on the view is something that is specific to how routes are handled in angular (and in this case, this is a valid issue)
I understood as if the issue was that the page was not scrolling to the id (as it does with the target="_self"
http://plnkr.co/edit/i2cKlukyrGAdXfhHOJ5e?p=preview)
I can't imagine how it would be possible to distinguish between _"scroll to #h1"_ and _"navigate to #h1"_, so other that what I mentioned above (https://github.com/angular/angular.js/issues/10105#issuecomment-63450792), I don't think there is much we can do about it.
Of course, we could have a special directive for "scrollTo" (or let the user build their own special directive).
(BTW, I have a feeling the new router will make it easy to apply my 2nd suggestion from above.)
I believe that this is working as expected. When $location
is turned on it make use of the hash char as explained by @gkalpak. The workarounds offered are adequate IMO and @bargitta has accepted this.
By the way, another option is to turn on HTML5 mode, which stops $location
from looking at the hash at all, I believe, but has its own idiosyncrasies.
Most helpful comment
I don't think this is unexpected. Angular recognizes
#
-prefixed paths as Angular paths (by default) and tries to route appropriately.If you want to be able to scroll to element using anchors, you should change the hash-prefix, so Angular won't recognize
#h1
as an Angular path:Then:
(Demo 1)
Alternatively, you can keep your current setup, but use the current path (as well as the hash) in anchors that should scroll to elements (not navigate to another route):
(Demo 2)
Finally, you can setup a function in your controller that uses
$location
'shash()
method to set the hash (in a way that lets Angular know it is a hash and not a path):Then:
(Demo 3)