web-dev-qa-db-fra.com

Angulaire ui-router défiler vers le haut, pas à ui-view

Je viens juste de passer de ui-router 0.2.8 à 0.2.0 et j'ai remarqué que lorsque l'état change, la position de défilement passe au sommet de l'enfant ui-view qui fait l'objet du nouvel état.

C’est bien, mais j’ai deux problèmes avec cela:

1) J'ai un remplissage de 30px entre le haut de la page et le ui-view et je voudrais qu'il défile en haut de la page, en laissant un espace. Pour le moment, cela va exactement au sommet du ui-view qui a l'air moche. Pour y parvenir, je suppose que je dois savoir comment le faire défiler vers le haut du div dans lequel se trouve la vue ui (et non le navigateur viewport), ou j'ai besoin de savoir comment remplacer $uiViewScroll pour passer au ui-view moins 30px.

J'ai essayé $uiViewScrollProvider.useAnchorScroll(); mais si je le fais, ça ne défile pas du tout. J'ai également essayé <ui-view autoscroll="false">;, qui arrête également le défilement complètement.

2) Il ne fait pas défiler pour le moment, mais saute. Est-il supposé faire défiler ou est-ce au développeur de le faire avec les transitions CSS?

Toute aide serait vraiment appréciée :)

64
jonhobbs

Une autre approche consiste à décorer le service $uiViewScroll par défaut, en remplaçant efficacement le comportement par défaut. 

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...
    }; 
  });
});

Et comme Hubrus l'a mentionné, pour tout <ui-view> pour lequel vous ne souhaitez pas que cela s'applique, ajoutez simplement autoscroll="false". Je n'ai pas bien examiné l'implémentation du défilement, je me suis juste dit que je mentionnerais la méthode du décorateur (c'est très amusant) comme alternative. Je suis sûr que vous pouvez déterminer le comportement exact du défilement. 

52
Kasper Lewau

chaque fois que le chemin change, le routeur diffuse un événement: $ stateChangeSuccess c’est-à-dire que l’URL a changé, écoutez-le simplement et utilisez jquery pour faire défiler vers le haut de la page.

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

placez le code ci-dessus à l'intérieur

yourAppName.run(function(){

    //the above code here
 })
41
Rishul Matta

J'ai donc eu le même problème. J'ai une barre de navigation à sommet fixe. Si je mets autoscroll = "true" dans la vue ui, il défilerait vers le haut, moins la hauteur de la hauteur de la barre de défilement.

Je me suis donc débarrassé du style qui ajoutait le rembourrage au corps de la barre de navigation supérieure

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

Et appliqué à la vue ui

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

Maintenant, autoscroll = "true" fonctionne comme prévu.

11
Martin

1) Je pense que la meilleure façon de mettre autoscroll="false" sur la vue interface utilisateur et de manipuler le défilement dans l'événement $viewContentLoaded.

2) Ceci est le comportement par défaut du navigateur sur les ancres

7
VladN

Étant donné que $stateChangeSuccess ne semble plus être disponible dans AngularJS actuel (en tant que 1.2.x), j’ai changé Exemple de Rishul Mattas, qui fonctionne bien pour moi:

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

Placer sur le dessus

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

Code à faire défiler:

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

Je pense qu'il n'est pas nécessaire de faire défiler l'écran vers le haut si l'état de navigation est un état enfant.

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

Si l’on combine conception angulaire et conception matérielle, il faut également faire défiler vers le haut:

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

La plupart du temps, il ne suffit pas de faire défiler vers le haut de la page. C'est toujours une bonne idée de respecter les liens d'ancrage et de faire défiler jusqu'à l'emplacement spécifique dans le contenu chargé désigné par le hachage de l'emplacement.

Voici le code que j'utilise pour mettre en œuvre cette stratégie:

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 est un événement généré par Angular lorsque le contenu est chargé à l'intérieur de l'élément ui-view. En réalité, nous devons différer l'exécution de notre code afin de le déplacer vers un prochain cycle de résumé. De cette manière, le contenu de l'élément view sera réellement placé dans l'arborescence DOM. Nous pouvons donc l'interroger. $timeout avec astuce zéro retard est utilisé à cette fin.

Le service $uiViewScroll, fourni par UI Router est utilisé pour faire le défilement. Nous pouvons lui passer un élément jQuery/jqLite et celui-ci défilera jusqu'au bord supérieur.

Nous obtenons le hachage de currect du service $location et l'utilisons pour trouver le bon élément à l'intérieur de l'arborescence DOM. Il peut s'agir d'un élément avec l'attribut id ou d'un lien avec l'attribut name. Si nous ne trouvons pas un élément à faire défiler, nous retombons dans un élément body (c’est-à-dire que nous allons faire défiler vers le haut de la page).

Et la findDomElement est juste un sucre syntaxique. Il a défini comme ceci:

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

J'espère que cette approche a du sens et sera utile à quelqu'un. À votre santé!

0
Slava Fomin II

Si vous voulez faire cela avec des vues conditionnellement, vous pouvez le placer dans la vue du contrôleur comme ceci:

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

ou éventuellement qui pourrait garder votre nettoyeur de fichier state.js, placez ce qui précède dans le contrôleur pour la vue donnée: 

function ExampleCtrl ($scope, $rootScope) {

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

J'espère que cela aide quelqu'un, s'il vous plaît faites le moi savoir si je manque quelque chose. J'ai utilisé ce dernier et fonctionne très bien pour moi.

0
alphapilgrim