How to handle anchor hash linking in AngularJS

后端 未结 27 884
后悔当初
后悔当初 2020-11-22 12:22

Do any of you know how to nicely handle anchor hash linking in AngularJS?

I have the following markup for a simple FAQ-page



        
相关标签:
27条回答
  • 2020-11-22 13:01

    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="scrollTo('foo')">Scroll to #foo</a>
    

    ...and no secret for the anchor id:

    <div id="foo">
      This is #foo
    </div>
    
    0 讨论(0)
  • 2020-11-22 13:02

    Get your scrolling feature easily. It also supports Animated/Smooth scrolling as an additional feature. Details for Angular Scroll library:

    Github - https://github.com/oblador/angular-scroll

    Bower: bower install --save angular-scroll

    npm : npm install --save angular-scroll

    Minfied version - only 9kb

    Smooth Scrolling (animated scrolling) - yes

    Scroll Spy - yes

    Documentation - excellent

    Demo - http://oblador.github.io/angular-scroll/

    Hope this helps.

    0 讨论(0)
  • 2020-11-22 13:03

    This was my solution using a directive which seems more Angular-y because we're dealing with the DOM:

    Plnkr over here

    github

    CODE

    angular.module('app', [])
    .directive('scrollTo', function ($location, $anchorScroll) {
      return function(scope, element, attrs) {
    
        element.bind('click', function(event) {
            event.stopPropagation();
            var off = scope.$on('$locationChangeStart', function(ev) {
                off();
                ev.preventDefault();
            });
            var location = attrs.scrollTo;
            $location.hash(location);
            $anchorScroll();
        });
    
      };
    });
    

    HTML

    <ul>
      <li><a href="" scroll-to="section1">Section 1</a></li>
      <li><a href="" scroll-to="section2">Section 2</a></li>
    </ul>
    
    <h1 id="section1">Hi, I'm section 1</h1>
    <p>
    Zombie ipsum reversus ab viral inferno, nam rick grimes malum cerebro. De carne lumbering animata corpora quaeritis. 
     Summus brains sit​​, morbo vel maleficia? De apocalypsi gorger omero undead survivor dictum mauris. 
    Hi mindless mortuis soulless creaturas, imo evil stalking monstra adventus resi dentevil vultus comedat cerebella viventium. 
    Nescio brains an Undead zombies. Sicut malus putrid voodoo horror. Nigh tofth eliv ingdead.
    </p>
    
    <h1 id="section2">I'm totally section 2</h1>
    <p>
    Zombie ipsum reversus ab viral inferno, nam rick grimes malum cerebro. De carne lumbering animata corpora quaeritis. 
     Summus brains sit​​, morbo vel maleficia? De apocalypsi gorger omero undead survivor dictum mauris. 
    Hi mindless mortuis soulless creaturas, imo evil stalking monstra adventus resi dentevil vultus comedat cerebella viventium. 
    Nescio brains an Undead zombies. Sicut malus putrid voodoo horror. Nigh tofth eliv ingdead.
    </p>
    

    I used the $anchorScroll service. To counteract the page-refresh that goes along with the hash changing I went ahead and cancelled the locationChangeStart event. This worked for me because I had a help page hooked up to an ng-switch and the refreshes would esentially break the app.

    0 讨论(0)
  • 2020-11-22 13:05

    $anchorScroll works for 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="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;
    });
    
    0 讨论(0)
  • 2020-11-22 13:05

    I am not 100% sure if this works all the time, but in my application this gives me the expected behavior.

    Lets say you are on ABOUT page and you have the following route:

    yourApp.config(['$routeProvider', 
        function($routeProvider) {
            $routeProvider.
                when('/about', {
                    templateUrl: 'about.html',
                    controller: 'AboutCtrl'
                }).
                otherwise({
                    redirectTo: '/'
                });
            }
    ]);
    

    Now, in you HTML

    <ul>
        <li><a href="#/about#tab1">First Part</a></li>
        <li><a href="#/about#tab2">Second Part</a></li>
        <li><a href="#/about#tab3">Third Part</a></li>                      
    </ul>
    
    <div id="tab1">1</div>
    <div id="tab2">2</div>
    <div id="tab3">3</div>
    

    In conclusion

    Including the page name before the anchor did the trick for me. Let me know about your thoughts.

    Downside

    This will re-render the page and then scroll to the anchor.

    UPDATE

    A better way is to add the following:

    <a href="#tab1" onclick="return false;">First Part</a>
    
    0 讨论(0)
  • 2020-11-22 13:05

    Based on @Stoyan I came up with the following solution:

    app.run(function($location, $anchorScroll){
        var uri = window.location.href;
    
        if(uri.length >= 4){
    
            var parts = uri.split('#!#');
            if(parts.length > 1){
                var anchor = parts[parts.length -1];
                $location.hash(anchor);
                $anchorScroll();
            }
        }
    });
    
    0 讨论(0)
提交回复
热议问题