2

I am trying to create an anchor in order to be able to build such an URL :

www.mysite.com/#myAnchor

which should automatically link to the div wanted, even from an exterior website. However, when I am trying to implement it, here is the adresse to which I am redirected : www.mysite.com/#/myAnchor

So far, I tested different things such as :

 <a name="myAnchor" />
 <a name="#myAnchor"></a>
 <a name="myAnchor"></a>
 <a href="#myAnchor" target="_self"></a>
 <span class="anchor " id="myAnchor"></span>

But nothing seems to work. However when I am on the page I can change the url to go there but from "outside" this just redirects to the top of the page.

Thanks for your help.

Diane Duquesne
  • 516
  • 2
  • 11
  • It's unclear why hash part of your anchored URL contains slash. The URL should be just `http://example.com/#myAnchor`. Also, the valid modern way to create an anchored element is to add an `id` to it like in `span` in your example code. – Marat Tanalin Nov 02 '15 at 23:57
  • Hi, sorry, I re-edited my question, actually this is the problem I figured out yesterday, my adress should not contain any #/ , but I have read that it was probably due to the presence of $location in my code. Cause even by testing the way you told me it doesn't work.. – Diane Duquesne Nov 03 '15 at 15:27

2 Answers2

0

That most likely happens because the first anchor is done by the browser, and when the page loads for the first time I assume the content is not all loaded yet (using views?).

If that is the case, then you need to call the service $anchorScroll that angular provides somewhere in your code after the view has been loaded (on a ng-init maybe?). Something like

<a name="myAnchor" ng-init="loadScrollToAnchor()"></a>

And then in your controller, after injecting the service $anchorScroll.

var scrolled = true;
$scope.loadScrollToAnchor = function () {
    if ( !scrolled ) {
        $anchorScroll();
        scrolled = true;
    }
};

Update: The scrolled variable is there to make sure that the code is only executed once (at page load), and thus this code should reside in an application-wise controller and not a controller specific to a route or view. However, there are still some shortcomings to this approach that might need to be countered, like if the view that the user loads the page first has no ng-init calling the function, and then he moves to another view that does: the code will execute, and the user viewport will possibly be changed against the user's intents.

Pedro M. Silva
  • 1,298
  • 2
  • 12
  • 23
  • Quick question : what the utility of the scrolled variable? – Diane Duquesne Nov 02 '15 at 22:39
  • Let's pretend that you changed views once and then came back. The ng-init code would run again, and the browser would scroll again to the document, even though that was not what the user probably wanted. The scrolled variable, if it lives in a controller that is not associated with the view, and thus is not destroyed on view change, ensures that the scroll code will only happen once (at load). – Pedro M. Silva Nov 02 '15 at 22:44
  • That still doesn't work, I really can't figure out why.. the adress should look like this www.mysite.com/#/myAnchor right? ( because it is an anchor ) – Diane Duquesne Nov 02 '15 at 22:50
  • No, as far as I know, the last slash is not necessary. It should look like this: www.mysite.com/#myAnchor – Pedro M. Silva Nov 02 '15 at 22:51
  • Ok, actually whenever I write /#myAnchor it automatically tranforms it to /#/myAnchor making the URL invalid. Any idea from where it can come? – Diane Duquesne Nov 02 '15 at 22:58
  • If you are using routing, it's probably the routing module. It uses the hash to determine the page, which makes it hard to use the hash to serve as an anchor. This answer has some strategies about it: http://stackoverflow.com/questions/14712223/how-to-handle-anchor-hash-linking-in-angularjs – Pedro M. Silva Nov 02 '15 at 23:00
0

To solve it, I actually only had to add this line of code without anything else :

<a href="#/my#Anchor"></a>

This is doing the trick.

Diane Duquesne
  • 516
  • 2
  • 11