UFO ET IT

Angular ui-router는 ui-view가 아닌 ​​맨 위로 스크롤합니다.

ufoet 2020. 11. 20. 17:26
반응형

Angular ui-router는 ui-view가 아닌 ​​맨 위로 스크롤합니다.


방금 ui-router 0.2.8from으로 업그레이드 0.2.0했고 상태가 변경되면 스크롤 위치가 ui-view새 상태의 주제 인 자식의 맨 위로 이동하는 것을 확인했습니다 .

이것은 괜찮지 만 두 가지 문제가 있습니다.

1) 페이지 상단과 사이에 30px 패딩이 있고 페이지 상단 ui-view으로 스크롤하여 간격을두고 싶습니다. 현재 그것은 ui-view추악 해 보이는 상단으로 정확하게 이동합니다 . 이를 달성하려면 ui-view가있는 div의 맨 위로 스크롤하도록하는 방법 (브라우저 viewport아님)을 알아야하거나 마이너스 30px $uiViewScroll로 스크롤하도록 재정의하는 방법을 찾아야한다고 생각합니다. ui-view.

나는 시도 $uiViewScrollProvider.useAnchorScroll();했지만 그렇게하면 전혀 스크롤되지 않습니다. 나는 또한 <ui-view autoscroll="false">;스크롤을 완전히 중지하는 시도했습니다 .

2) 실제로 스크롤하지 않고 점프 만합니다. 스크롤을 가정합니까 아니면 CSS 전환으로이를 수행하는 것은 개발자의 몫입니까?

어떤 도움이라도 정말 감사하겠습니다 :)


또 다른 접근 방식은 기본 $uiViewScroll서비스 를 장식 하여 기본 동작을 효과적으로 재정의하는 것입니다.

app.config(function ($provide) {
  $provide.decorator('$uiViewScroll', function ($delegate) {
    return function (uiViewElement) {
      // var top = uiViewElement.getBoundingClientRect().top;
      // window.scrollTo(0, (top - 30));
      // Or some other custom behaviour...
    }; 
  });
});

Hubrus가 언급했듯이이 <ui-view>신청을 원하지 않는 사람은 간단히 autoscroll="false". 나는 실제 스크롤 구현에 대해 잘 보지 않았고, 대안으로 데코레이터 방식 (많은 재미)을 언급 할 것이라고 생각했습니다. 정확한 스크롤 동작을 해결할 수 있다고 확신합니다.


경로가 변경 될 때마다 라우터는 이벤트를 브로드 캐스트합니다. $ stateChangeSuccess 즉, URL이 변경되었으므로이를 듣고 jquery를 사용하여 페이지 상단으로 스크롤하십시오.

$rootScope.$on('$stateChangeSuccess',function(){
    $("html, body").animate({ scrollTop: 0 }, 200);
})

위의 코드를 안에 넣으십시오.

yourAppName.run(function(){

    //the above code here
 })

그래서 나는 이와 같은 문제가있었습니다. 고정 상단 탐색 모음이 있습니다. ui-view에 autoscroll = "true"를 넣으면 스크롤 막대의 높이를 뺀 상단으로 스크롤됩니다.

그래서 상단 탐색 메뉴의 본문에 패딩을 추가 한 스타일을 제거했습니다.

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

그리고 그것을 ui-view에 적용했습니다.

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

이제 autoscroll = "true"가 예상대로 작동합니다.


1) autoscroll="false"ui-view에 올려 놓고 $viewContentLoaded이벤트 에서 스크롤링을 조작하는 가장 쉬운 방법이라고 생각합니다 .

2) 이것은 앵커에 대한 브라우저의 기본 동작입니다.


$stateChangeSuccess현재 AngularJS (1.2.x)에서 더 이상 사용할 수없는 것 같기 때문에 Rishul Mattas 예제를 다음과 같이 변경했습니다.

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

위에 놓기

<div id="top">.....

스크롤 할 코드 :

$rootScope.$on('$stateChangeStart', function() {
    $anchorScroll('top');
});

Angular + Material Design을 결합한 경우 맨 위로 스크롤해야합니다.

app.run(function ($rootScope) {
    $rootScope.$on('$viewContentLoaded', function () {
        $("md-content").animate({ scrollTop: 0 }, "fast"); /* <------- Notice this line */
        jQuery('html, body').animate({ scrollTop: 0 }, 200);
    });
});

탐색 상태가 자식 상태이면 맨 위로 스크롤 할 필요가 없다고 생각하므로 다음과 같이 썼습니다.

$rootScope.$on('$stateChangeSuccess',function(_, _, _, os){
    if(!$state.includes(os) || $state.is(os))
        $("html, body").animate({ scrollTop: 0 }, 200);
});

대부분의 경우 페이지 상단으로 스크롤하는 것만으로는 충분하지 않습니다. 항상 앵커 링크를 존중하고 위치의 해시로 지정된로드 된 콘텐츠의 특정 위치로 스크롤하는 것이 좋습니다.

이 전략을 구현하는 데 사용하는 코드는 다음과 같습니다.

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!


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.

참고URL : https://stackoverflow.com/questions/22290570/angular-ui-router-scroll-to-top-not-to-ui-view

반응형