Angular ui-router scroll to top, not to ui-view

后端 未结 10 1387
情话喂你
情话喂你 2020-12-12 16:00

I\'ve just upgraded to ui-router 0.2.8 from 0.2.0 and I\'ve noticed that when the state changes, the scroll position jumps to the top of te child <

10条回答
  •  一向
    一向 (楼主)
    2020-12-12 16:46

    Most of the time it's not enough just to scroll to the top of the page. It is always a good idea to respect anchor links and to scroll to the specific place in the loaded content designated by location's hash.

    Here's the code I use to implement this strategy:

    module.run(function (
      $rootScope,
      $timeout,
      $location,
      $uiViewScroll
    ) {
    
      // Scrolling when screen changed.
      $rootScope.$on('$viewContentLoaded', function () {
        $timeout(performAutoScroll, 0);
      });
    
    
      function performAutoScroll () {
        var hash = $location.hash();
        var element =
             findDomElement('#' + hash)
          || findDomElement('a[name="' + hash + '"]')
          || angular.element(window.document.body)
        ;
        $uiViewScroll(element);
      }
    });
    

    $viewContentLoaded is an event generated by Angular when content is loaded inside of the ui-view element. Actually, we need to postpone the execution of our code in order to move it to a next digest cycle. That way the content of the view element will be actually placed in the DOM tree, so we can query it. $timeout with zero delay trick is used for this purpose.

    $uiViewScroll service, provided by UI Router is used to actually do the scrolling. We can pass a jQuery/jqLite element to it and it will scroll to it's top border.

    We are getting the currect hash from the $location service and using it to find the proper element inside of the DOM tree. It could be either a element with id attribute or a link with name attribute. In case we can't find an element to scroll to we falling back to a body element (i.e. will scroll to the top of the page).

    And the findDomElement is just a syntactic sugar. It defined like this:

    /**
     * @param {string} selector
     * @returns {jQuery|null}
     */
    function findDomElement (selector) {
      var result = $(selector);
      return (result.length > 0 ? result : null);
    }
    

    I hope this approach makes sense and will be useful to someone out there. Cheers!

提交回复
热议问题