Angular ui-router прокрутите вверх, а не в ui-view

Я только что обновил до ui-router 0.2.8 от 0.2.0, и я заметил, что при изменении состояния положение прокрутки переместится в начало te child ui-view, которое является предметом нового состояния.

Это хорошо, но у меня есть две проблемы:

1) У меня есть 30px отступы между верхней частью страницы и ui-view, и я бы хотел, чтобы она прокручивалась до верхней части страницы, оставляя пробел. На данный момент он идет точно к вершине ui-view, которая выглядит уродливой. Чтобы достичь этого, я думаю, мне нужно знать, как заставить его прокручивать вверху div, в котором находится ui-view (а не в браузере viewport), или мне нужно выяснить, как переопределить $uiViewScroll для прокрутки до ui-view минус 30px.

Я пробовал $uiViewScrollProvider.useAnchorScroll();, но если я это сделаю, он вообще не прокручивается. Я также пробовал <ui-view autoscroll="false">;, который также полностью останавливает прокрутку.

2) На данный момент он фактически не прокручивается, просто прыгает. Предполагается ли прокрутка или это зависит от разработчика, чтобы сделать это с переходами CSS?

Любая помощь будет действительно оценена:)

Ответ 1

Другой подход заключается в том, чтобы украсить службу по умолчанию $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...
    }; 
  });
});

И как сказал Хубрус, для любого <ui-view> вы не хотите, чтобы это было выражение, просто добавьте autoscroll="false". Я не очень хорошо посмотрел на реальную реализацию прокрутки, я просто подумал, что в качестве альтернативы я бы упомянул стиль декоратора (это много удовольствия). Я уверен, что вы сможете выработать точное поведение прокрутки.

Ответ 2

когда когда-либо путь изменяет маршрутизатор, он передает событие: $stateChangeSuccess, т.е. URL-адрес изменился, поэтому просто прослушайте его и используйте jquery для прокрутки вверху страницы

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

поместите вышеуказанный код внутри

yourAppName.run(function(){

    //the above code here
 })

Ответ 3

Итак, у меня была такая же проблема. У меня есть фиксированная верхняя панель навигации. Если я положил autoscroll = "true" в u-view, он прокрутил бы вверх до минус высота высоты полосы прокрутки.

Итак, я избавился от стиля, который добавил прокладку к телу для верхней панели навигации

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

И применил его к ui-view

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

Теперь autoscroll = "true" работает как ожидалось.

Ответ 4

1) Я думаю, что самый простой способ разместить autoscroll="false" на ui-view и манипулировать прокруткой в ​​событии $viewContentLoaded.

2) Это поведение браузера по умолчанию на якоря

Ответ 5

Так как $stateChangeSuccess, похоже, больше не доступен в текущем AngularJS (как 1.2.x), я изменил Пример Ришула Маттаса к следующему, который отлично подходит для меня:

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

Ответ 6

Место сверху

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

Код для прокрутки:

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

Ответ 7

Если вы комбинируете 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);
    });
});

Ответ 8

Я думаю, что нам не нужно прокручивать вверх, если навигационное состояние является дочерним, поэтому я написал это:

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

Ответ 9

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

Вот код, который я использую для реализации этой стратегии:

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 - событие, генерируемое Angular, когда содержимое загружается внутри элемента ui-view. На самом деле нам нужно отложить выполнение нашего кода, чтобы переместить его в следующий цикл дайджеста. Таким образом, содержимое элемента представления будет фактически помещено в дерево DOM, поэтому мы можем запросить его. $timeout с трюком с нулевой задержкой используется для этой цели.

$uiViewScroll услуга, предоставляемая UI Router, используется для фактической прокрутки. Мы можем передать ему элемент jQuery/jqLite, и он прокрутит к нему верхнюю границу.

Мы получаем личный хэш из службы $location и используем его для поиска правильного элемента внутри дерева DOM. Это может быть либо элемент с атрибутом id, либо ссылка с атрибутом name. В случае, если мы не можем найти элемент для прокрутки, мы возвращаемся к элементу body (т.е. Прокручиваем вверх страницы).

И findDomElement - это просто синтаксический сахар. Он определяется следующим образом:

/**
 * @param {string} selector
 * @returns {jQuery|null}
 */
function findDomElement (selector) {
  var result = $(selector);
  return (result.length > 0 ? result : null);
}

Я надеюсь, что этот подход имеет смысл и будет полезен кому-то там. Ура!

Ответ 10

Если вы хотите сделать это с условными условными обозначениями, вы можете поместить это в представление контроллера следующим образом:

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

или, возможно, это может привести к тому, что ваш очиститель файла state.js помещает вышеприведенное в контроллер для данного вида:

function ExampleCtrl ($scope, $rootScope) {

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

Надеюсь, это поможет кому-то, пожалуйста, дайте мне знать, если я что-то упустил. Я использовал последнее и отлично поработал у меня.