AngularJS: автоматическая прокрутка до точки привязки после изменения состояния

Я хочу, чтобы пользователь щелкнул ссылку на странице, это вызовет изменение состояния и приведет их к новому состоянию. чего я хочу добиться, так это того, что когда состояние завершает загрузку, оно затем прокручивается до привязки на странице, указанной ссылкой на предыдущей странице.

Для этого я использую комбинацию передачи $stateParam через ui-sref следующим образом:

<a ui-sref="stateParent.stateChild({id: 'practiceParam'})">goToPage</a>

затем, когда страница достигнута, на ней находится div с прикрепленной директивой, которая активируется на $viewContentLoaded, поэтому DOM отображается, и я могу искать идентификатор. HTML div выглядит так:

<div scroll-after-load ></div>

и моя директива прокрутки выглядит следующим образом:

angular.module( 'app' ).directive('scrollAfterLoad', function() {
  return {
    restrict: 'A',
    link: function(scope, $elm, attrs, $stateParams) {
        scope.$on('$viewContentLoaded', function() {
            console.log('scrollAfterLoad Directive Loaded, $stateParams are: ', $stateParams );
            var idToScroll = attrs.href;
            var $target;
            if (idToScroll) {
                $target = $(idToScroll);
                // the -50 accounts for the top navbar which is fixed on the page and removed from pageflow
                $("html,body").animate({scrollTop: $target.offset().top - 50}, "slow");
            }
        });
    }
  };
});

Я еще не удосужился установить href в div, так как не могу получить доступ к переданному параметру, я неправильно обращаюсь к нему? Я также пытался использовать более стандартный state.go() для передачи stateParam, но мой результат по-прежнему равен нулю.

Как только я могу передать параметр состояния, идея состоит в том, чтобы просто добавить href к параметрам, который вводится в div на вновь загруженной странице, и автоматически прокручивать до другого div на этой странице с идентификатором, который соответствует моему переданному параметру.

Кроме того, примечание: в моем пользовательском интерфейсе для автопрокрутки установлено значение true, поэтому страницы автоматически загружаются вверху, мне нравится такое поведение, и именно поэтому мне нужно, чтобы состояние завершило загрузку до активации прокрутки.


person Eolis    schedule 15.10.2015    source источник
comment
интересное решение, но я предпочитаю избегать дополнительных зависимостей в моем проекте и писать для него простую директиву.   -  person Eolis    schedule 16.10.2015


Ответы (2)


Ваша проблема в том, что вы пытаетесь внедрить службу $stateParams в функцию ссылки. Тем не менее, правильное место для этого вида впрыска - заводской метод, что означает определение директивы. Фабричный метод регистрируется с модулем - как в вашем случае с директивой scrollAfterLoad. Для получения дополнительной информации см. Injection Dependency AngularJS.

Итак, вернемся к вашему вопросу: если вы действительно вводите $stateParams в свой фабричный метод своей директивы, значит, вверху вы сможете легко получить доступ к параметрам. Ваша директива может выглядеть так:

angular.module( 'app' ).directive('scrollAfterLoad', ['$stateParams', function($stateParams) {
  return {
    restrict: 'A',
    link: function(scope, $elm, attrs) {
        scope.$on('$viewContentLoaded', function() {
            console.log('scrollAfterLoad Directive Loaded, $stateParams are: ', $stateParams );
            var idToScroll = attrs.href;
            var $target;
            if (idToScroll) {
                $target = $(idToScroll);
                // the -50 accounts for the top navbar which is fixed on the page and removed from pageflow
                $("html,body").animate({scrollTop: $target.offset().top - 50}, "slow");
            }
        });
    }
  };
}]);

Обратите внимание, что я удалил $stateParams из вашей функции ссылки и поместил ее вверху. Таким образом, услуга уже будет доступна в функции ссылки - фактически во всей директиве.

Я воспроизвел ваш сценарий в этом планкере.

person LordTribual    schedule 15.10.2015
comment
Я вижу, это имеет смысл, и у меня есть параметры, работающие в моем проекте. Большое спасибо за помощь! надеялся, что я просто помещал что-то не в то место или неправильно обращался к параметрам. - person Eolis; 16.10.2015

С помощью angular-scroll вы можете сделать это следующим образом:

Передайте свой scroll target id в качестве параметра состояния дочернему контроллеру состояния, а затем прокрутите до элемента с scrollToAnimated(element).

Если вы хотите, чтобы его можно было использовать повторно, вы можете создать фабрику этого контроллера и внедрить его в разрешение дочернего состояния. Тоже должно работать, но я не проверял.

Вам, вероятно, нужно повторно запустить прокрутку, если вы находитесь в дочернем состоянии, и снова щелкнуть ссылку изменения состояния. Вот почему я добавил метод checkState, который перезагружает текущее состояние, если мы находимся в дочернем состоянии, чтобы повторить прокрутку.

Посмотрите демонстрацию ниже или в этой скрипте.

Я думаю, что ваша директива не работает, потому что вы не передаете атрибут href в свою директиву.

Вы можете исправить это, передав href="targetId" в свою директиву, где targetId добавляется с $scope.targetId = $stateParams.id в вашем дочернем контроллере. Или вы можете получить доступ к targetId из $scope напрямую, если вы не используете изолированную область.

В любом случае, я бы сделал это так же, как в демоверсии, или с фабрикой внутри разрешения.

angular.module('demoApp', ['ui.router', 'duScroll'])
	.controller('MainControlller', MainController)
	.config(Config);

function MainController($scope, $state) {
	$scope.checkState = function() {
    	//console.log($state.current);
        if($state.current.name == 'parent.child') {
            //console.log('parent.child state');
        	// reload to retrigger scrolling again
           $state.reload();
        }
    };
}

function Config($urlRouterProvider, $stateProvider) {
	$urlRouterProvider.otherwise('/');
    
    $stateProvider
    	.state('parent', {
        	url: '/',
        	templateUrl: 'home.html'
    })
    	.state('parent.child', {
    	url: 'child/:id',
        templateUrl: 'child.html',
        controller: function($scope, $stateParams, $document) {
        	var scrollElement = angular
                .element(document.getElementById($stateParams.id));
            console.log(scrollElement);
            $document.scrollToElementAnimated(scrollElement);
        }
    });
               
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-scroll/0.7.3/angular-scroll.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.15/angular-ui-router.js"></script>
<div ng-app="demoApp" ng-controller="MainController">
    <script type="text/ng-template" id="home.html">
        <a ui-sref="parent.child({id: 'practiceParam'})" ng-click="checkState()">go to practice</a>
        <div ui-view=""></div>
    </script>
    <script type="text/ng-template" id="child.html">
        <!--<a href="#practiceParam" du-smooth-scroll="">scroll to practice</a>
        --><p>
            Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. 
        </p><p>
Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. 
        </p><p>
Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.</p>
<p>
Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. 
        </p>
        <p>
            Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. 
        </p>
        <h1 id="practiceParam">practice</h1>
        <p>
Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. 
        </p><p>
Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.</p>
<p>
Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. 
        </p>
        <a ui-sref="parent">back</a>
    </script>
    
    <div ui-view=""></div>
</div>

person AWolf    schedule 15.10.2015