Как «запомнить» положение прокрутки в angularJS с Ui.ROUTER

У меня есть проект, в котором я использую angularJS с ui.router, и у нас есть список событий, который может быть очень длинным (имеет бесконечную прокрутку), если пользователь нажимает на событие, чтобы просмотреть подробности, отображается кнопка «Назад», однако при нажатии кнопки «Назад» прокрутка div сбрасывается обратно наверх! Ищу некоторые предложения относительно того, есть ли что-то встроенное, что я мог бы использовать, чтобы запомнить эту позицию прокрутки, я знаю, что есть служба anchorscroll, но мне интересно, нет ли чего-то более подходящего, чтобы остановить angular от сброса позиций прокрутки при навигации ?? так как есть несколько подобных списков, которые должны помнить свое состояние при прокрутке. Я изучил и попытался реализовать ui-router-extras dsr и sticky, но ни один из них не работает..
пример в http://codedef.com/hapzis_poc/ . не полное доказательство, но должна иметь возможность прокручивать события вниз, нажимать «о» и «назад» и оставаться в той же позиции прокрутки.


person DavidMIRV    schedule 03.03.2015    source источник


Ответы (2)


Есть разговор на аналогичную тему (ng-view), и ответ, данный @br2000, у меня сработал.

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

Чтобы его директива работала на ui-router, сделайте следующее:

<сильный>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. Используйте его для элемента, у которого есть атрибут ui-view, в моем случае:

<div class="col-xs-12" ui-view keep-scroll-pos></div>
person Marcin Rapacz    schedule 02.03.2016
comment
$timeout(function () { $window.scrollTo(prevScrollPos[0], prevScrollPos[1]); }, 1000); => подождите 1 секунду, пока страница отобразится... - person Phung D. An; 06.05.2016
comment
Вам не нужно $route в 8-й строке. - person trojek; 26.04.2018

Чтобы прикрепляемые состояния работали, вы не должны уничтожать элемент DOM. Глядя на структуру вашего состояния, вы используете именованный ui-view body для состояния home в соответствии с документацией ui-router-extras. Однако затем вы стираете этот элемент ui-view при переходе в состояние about, которое также использует 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'
            }
        }
    });

Убедитесь, что пользовательский интерфейс закрепленного состояния не используется повторно. Для вашего примера поместите состояние about в безымянное представление.

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

индекс.html:

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

js:

app.run(function($rootScope, $state) { $rootScope.$state = $state } );
person Chris T    schedule 03.03.2015