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

后端 未结 10 1343
情话喂你
情话喂你 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:34

    If you wanted to do this with views conditionally, you could place this in the controller view like so:

    .state('exampleState', {
        url: '/exampleURL',
        controller: 'ExampleCtrl as examplectrl',
        onEnter: function($rootScope) {
                $rootScope.$on('$viewContentLoaded',function(){
                jQuery('html, body').animate({ scrollTop: 0 }, 200);
            });
        }
    }).
    

    or optionally which might keep your state.js file cleaner place the above in the controller for given view:

    function ExampleCtrl ($scope, $rootScope) {
    
        $rootScope.$on('$viewContentLoaded',function(){
                jQuery('html, body').animate({ scrollTop: 0 }, 200);
            });
    }
    

    Hope this helps someone, please let me know if I'm missing something. I used the latter and works great for me.

    0 讨论(0)
  • 2020-12-12 16:35

    So I had this same problem. I have a fixed-top nav bar. If I put autoscroll="true" in the ui-view it would scroll to the top minus the height of the height of the scroll bar.

    So I got rid of the style that added the padding to the body for the top navbar

    // fixed navigation at top
    //body { padding-top: 100px; }
    

    And applied it to the ui-view

    [ui-view=main] {
        padding-top: 100px;
    }
    

    Now autoscroll="true" works as expected.

    0 讨论(0)
  • 2020-12-12 16:37

    I think that we don't need scrolling to top if navigating state is child state, so I wrote this:

    $rootScope.$on('$stateChangeSuccess',function(_, _, _, os){
        if(!$state.includes(os) || $state.is(os))
            $("html, body").animate({ scrollTop: 0 }, 200);
    });
    
    0 讨论(0)
  • 2020-12-12 16:41

    1) I think the easiest way it to put autoscroll="false" on the ui-view and manipulate the scrolling in the $viewContentLoaded event.

    2) This is the browser's default behavior on anchors

    0 讨论(0)
  • 2020-12-12 16:45

    If one combines Angular + Material Design, this is also required to scroll to top:

    app.run(function ($rootScope) {
        $rootScope.$on('$viewContentLoaded', function () {
            $("md-content").animate({ scrollTop: 0 }, "fast"); /* <------- Notice this line */
            jQuery('html, body').animate({ scrollTop: 0 }, 200);
        });
    });
    
    0 讨论(0)
  • 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!

    0 讨论(0)
提交回复
热议问题