Anchor links in Angularjs?

The question:

Is it possible to use anchor links with Angularjs?

I.e.:

 <a href="#top" rel="nofollow noreferrer noopener">Top</a>
 <a href="#middle" rel="nofollow noreferrer noopener">Middle</a>
 <a href="#bottom" rel="nofollow noreferrer noopener">Bottom</a>

 <div name="top"></div>
 ...
 <div name="middle"></div>
 ...
 <div name="bottom"></div>

Thank you

The Solutions:

Below are the methods you can try. The first solution is probably the best. Try others if the first one doesn’t work. Senior developers aren’t just copying/pasting – they read the methods carefully & apply them wisely to each case.

Method 1

There are a few ways to do this it seems.

Option 1: Native Angular

Angular provides an $anchorScroll service, but the documentation is severely lacking and I’ve not been able to get it to work.

Check out http://www.benlesh.com/2013/02/angular-js-scrolling-to-element-by-id.html for some insight into $anchorScroll.

Option 2: Custom Directive / Native JavaScript

Another way I tested out was creating a custom directive and using el.scrollIntoView().
This works pretty decently by basically doing the following in your directive link function:

var el = document.getElementById(attrs.href);
el.scrollIntoView();

However, it seems a bit overblown to do both of these when the browser natively supports this, right?

Option 3: Angular Override / Native Browser

If you take a look at http://docs.angularjs.org/guide/dev_guide.services.$location and its HTML Link Rewriting section, you’ll see that links are not rewritten in the following:

Links that contain target element

Example: <a href="/ext/link?a=b" rel="nofollow noreferrer noopener" target="_self">link</a>

So, all you have to do is add the target attribute to your links, like so:

<a href="#anchorLinkID" rel="nofollow noreferrer noopener" target="_self">Go to inpage section</a>

Angular defaults to the browser and since its an anchor link and not a different base url, the browser scrolls to the correct location, as desired.

I went with option 3 because its best to rely on native browser functionality here, and saves us time and effort.

Gotta note that after a successful scroll and hash change, Angular does follow up and rewrite the hash to its custom style. However, the browser has already completed its business and you are good to go.

Method 2

I don’t know if that answers your question, but yes, you can use angularjs links, such as:

<a ng-href="http://www.gravatar.com/avatar/{{hash}}" rel="nofollow noreferrer noopener"/>

There is a good example on the AngularJS website:

http://docs.angularjs.org/api/ng.directive:ngHref

UPDATE: The AngularJS documentation was a bit obscure and it didn’t provide a good solution for it. Sorry!

You can find a better solution here: How to handle anchor hash linking in AngularJS

Method 3

You could try to use anchorScroll.

Example

So the controller would be:

app.controller('MainCtrl', function($scope, $location, $anchorScroll, $routeParams) {
  $scope.scrollTo = function(id) {
     $location.hash(id);
     $anchorScroll();
  }
});

And the view:

<a href="" ng-click=" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener"scrollTo('foo')">Scroll to #foo</a>

…and no secret for the anchor id:

<div id="foo">
  This is #foo
</div>

Method 4

$anchorScroll is indeed the answer to this, but there’s a much better way to use it in more recent versions of Angular.

Now, $anchorScroll accepts the hash as an optional argument, so you don’t have to change $location.hash at all. (documentation)

This is the best solution because it doesn’t affect the route at all. I couldn’t get any of the other solutions to work because I’m using ngRoute and the route would reload as soon as I set $location.hash(id), before $anchorScroll could do its magic.

Here is how to use it… first, in the directive or controller:

$scope.scrollTo = function (id) {
  $anchorScroll(id);  
}

and then in the view:

<a href="" ng-click=" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener"scrollTo(id)">Text</a>

Also, if you need to account for a fixed navbar (or other UI), you can set the offset for $anchorScroll like this (in the main module’s run function):

  .run(function ($anchorScroll) {
      //this will make anchorScroll scroll to the div minus 50px
      $anchorScroll.yOffset = 50;
  });

Method 5

I had the same problem, but this worked for me:

<a ng-href="javascript:void(0);#tagId" rel="nofollow noreferrer noopener"></a>

Method 6

Works for me:

 <a onclick='return false;' href="" class=" rel="nofollow noreferrer noopener"collapsed" role="button" data-toggle="collapse" data-parent="#accordion" ng-href="#profile#collapse{{$index}}" rel="nofollow noreferrer noopener"> blalba </a>

Method 7

You need to only add target=”_self” to your link

ex. <a href="#services" target="_self">Services</a><div id="services"></div>

Method 8

Or you could simply write:

ng-href="#yourAnchorId" rel="nofollow noreferrer noopener"

Please notice the backslash in front of the hash symbol

Method 9

If you are using SharePoint and angular then do it like below:

<a ng-href="{{item.LinkTo.Url}}" rel="nofollow noreferrer noopener" target="_blank" ng-bind="item.Title;" ></a> 

where
LinkTo and Title is SharePoint Column.

Method 10

The best choice to me was to create a directive to do the work, because $location.hash() and
$anchorScroll() hijack the URL creating lots of problems to my SPA routing.

MyModule.directive('myAnchor', function() {
  return {
    restrict: 'A',
    require: '?ngModel',
    link: function(scope, elem, attrs, ngModel) {
      return elem.bind('click', function() {
        //other stuff ...
        var el;
        el = document.getElementById(attrs['myAnchor']);
        return el.scrollIntoView();
      });      
    }
  };
});

Method 11

You can also Navigate to HTML id from inside controller

$location.hash('id_in_html');


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Comment