如何“记住”angularJS w / Ui.ROUTER中的滚动位置

时间:2021-12-04 11:39:47

I have a project I'm using angularJS with ui.router and we have a list of events that can be really long (has infinite scroll) if a user clicks on an event to view details a back button is displayed however upon clicking back the scroll of the div resets back to the top! Looking for some suggestions as to if there is anything built in that I might leverage to remember this scroll position, I know theres the anchorscroll service but I am wondering if there isn't something more suited to stop angular from reseting the scroll positions on navigation?? as there are a few similar lists to this that need to remember their state when scrolled.. I've looked into and tried to implement ui-router-extras dsr and sticky but neither are working..
example at http://codedef.com/hapzis_poc/ . not a full proof but should be able to scroll down the events , click about and back and stay in same scroll position..

我有一个项目我正在使用带有ui.router的angularJS,如果用户点击某个事件来查看详细信息,则会显示一个后退按钮但是在点击后面时,我们会有一个非常长的事件列表(具有无限滚动) div的滚动重置回顶部!寻找一些关于是否有内置的建议,我可以利用它来记住这个滚动位置,我知道有关于anchorscroll服务但是我想知道是否有更适合停止角度来重置导航上的滚动位置??因为有一些类似的列表需要在滚动时记住它们的状态..我已经查看并试图实现ui-router-extras dsr和sticky但是两者都没有工作..示例在http:// codedef。 com / hapzis_poc /。不是完整的证明,但应该能够向下滚动事件,点击并返回并保持在相同的滚动位置..

2 个解决方案

#1


1  

There is a conversation on the similar topic (ng-view) and the answer given by @br2000 worked for me.

关于类似主题(ng-view)的讨论和@ br2000给出的答案对我有用。

https://*.com/a/25073496/3959662

To make his directive work for ui-router do the following:

要使他的指令适用于ui-router,请执行以下操作:

1. Create new directive like this:

1.像这样创建新指令:

(function () {
    'use strict';

    angular
        .module('your.module.directives')
        .directive('keepScrollPos', keepScrollPos);

    function keepScrollPos($route, $window, $timeout, $location, $anchorScroll, $state) {

        // cache scroll position of each route's templateUrl
        var scrollPosCache = {};

        // compile function
        var directive = function (scope, element, attrs) {

            scope.$on('$stateChangeStart', function () {
                // store scroll position for the current view
                if($state.$current)
                { 
                    scrollPosCache[$state.current.templateUrl] = [$window.pageXOffset, $window.pageYOffset];
                }
             });

            scope.$on('$stateChangeSuccess', function () {
                // if hash is specified explicitly, it trumps previously stored scroll position
                if ($location.hash()) {
                    $anchorScroll();

                // else get previous scroll position; if none, scroll to the top of the page
                } else {
                    var prevScrollPos = scrollPosCache[$state.current.templateUrl] || [0, 0];
                    $timeout(function () {
                        $window.scrollTo(prevScrollPos[0], prevScrollPos[1]);
                }, 0);
            }
        });
    };

    return directive;
}
})();

2. Use it on the element you have the ui-view attribute, in my case:

2.在我拥有ui-view属性的元素上使用它,在我的例子中:

<div class="col-xs-12" ui-view keep-scroll-pos></div>

#2


0  

For sticky states to work, you must not destroy the DOM element. Looking at your state structure, you are using the named ui-view body for state home, as per the ui-router-extras documentation. However, you then clobber that ui-view element when transitioning to about state, which also uses the body ui-view. This can be observed by inspecting the DOM.

要使粘性状态起作用,您不能破坏DOM元素。查看状态结构,根据ui-router-extras文档,您将使用命名的ui-view主体进行状态主页。然而,当你转换到about状态时,你会破坏那个ui-view元素,这也是使用body ui-view。通过检查DOM可以观察到这一点。

.state('home', {
        url: "",
        deepStateRedirect: true,
        sticky: true,
        views: {
            "body": {
                templateUrl: 'templates/home.html'
            },
            "event_list@home": {
                sticky: true,
                templateUrl: "templates/eventList.html",
                controller: "eventListCtrl"
            }
        }
    })
    .state('about', {
        url: 'about',
        views: {
            "body": { // BAD, you just clobbered the sticky ui-view with this template
                templateUrl: 'templates/about.html'
            }
        }
    });

Make sure the sticky state's ui-view is not re-used. For your example, put about state in the unnamed view.

确保不会重复使用粘性状态的ui-view。对于您的示例,将状态放在未命名的视图中。

    .state('about', {
        url: 'about',
        templateUrl: 'templates/about.html'
    });

index.html:

<div ui-view="body" ng-show="$state.includes('home')"></div>
<div ui-view></div>

js:

app.run(function($rootScope, $state) { $rootScope.$state = $state } );

#1


1  

There is a conversation on the similar topic (ng-view) and the answer given by @br2000 worked for me.

关于类似主题(ng-view)的讨论和@ br2000给出的答案对我有用。

https://*.com/a/25073496/3959662

To make his directive work for ui-router do the following:

要使他的指令适用于ui-router,请执行以下操作:

1. Create new directive like this:

1.像这样创建新指令:

(function () {
    'use strict';

    angular
        .module('your.module.directives')
        .directive('keepScrollPos', keepScrollPos);

    function keepScrollPos($route, $window, $timeout, $location, $anchorScroll, $state) {

        // cache scroll position of each route's templateUrl
        var scrollPosCache = {};

        // compile function
        var directive = function (scope, element, attrs) {

            scope.$on('$stateChangeStart', function () {
                // store scroll position for the current view
                if($state.$current)
                { 
                    scrollPosCache[$state.current.templateUrl] = [$window.pageXOffset, $window.pageYOffset];
                }
             });

            scope.$on('$stateChangeSuccess', function () {
                // if hash is specified explicitly, it trumps previously stored scroll position
                if ($location.hash()) {
                    $anchorScroll();

                // else get previous scroll position; if none, scroll to the top of the page
                } else {
                    var prevScrollPos = scrollPosCache[$state.current.templateUrl] || [0, 0];
                    $timeout(function () {
                        $window.scrollTo(prevScrollPos[0], prevScrollPos[1]);
                }, 0);
            }
        });
    };

    return directive;
}
})();

2. Use it on the element you have the ui-view attribute, in my case:

2.在我拥有ui-view属性的元素上使用它,在我的例子中:

<div class="col-xs-12" ui-view keep-scroll-pos></div>

#2


0  

For sticky states to work, you must not destroy the DOM element. Looking at your state structure, you are using the named ui-view body for state home, as per the ui-router-extras documentation. However, you then clobber that ui-view element when transitioning to about state, which also uses the body ui-view. This can be observed by inspecting the DOM.

要使粘性状态起作用,您不能破坏DOM元素。查看状态结构,根据ui-router-extras文档,您将使用命名的ui-view主体进行状态主页。然而,当你转换到about状态时,你会破坏那个ui-view元素,这也是使用body ui-view。通过检查DOM可以观察到这一点。

.state('home', {
        url: "",
        deepStateRedirect: true,
        sticky: true,
        views: {
            "body": {
                templateUrl: 'templates/home.html'
            },
            "event_list@home": {
                sticky: true,
                templateUrl: "templates/eventList.html",
                controller: "eventListCtrl"
            }
        }
    })
    .state('about', {
        url: 'about',
        views: {
            "body": { // BAD, you just clobbered the sticky ui-view with this template
                templateUrl: 'templates/about.html'
            }
        }
    });

Make sure the sticky state's ui-view is not re-used. For your example, put about state in the unnamed view.

确保不会重复使用粘性状态的ui-view。对于您的示例,将状态放在未命名的视图中。

    .state('about', {
        url: 'about',
        templateUrl: 'templates/about.html'
    });

index.html:

<div ui-view="body" ng-show="$state.includes('home')"></div>
<div ui-view></div>

js:

app.run(function($rootScope, $state) { $rootScope.$state = $state } );