La modifica del percorso non scorre verso l’alto nella nuova pagina

Ho trovato un comportamento indesiderato, almeno per me, quando il percorso cambia. Nel passaggio 11 del tutorial http://angular.github.io/angular-phonecat/step-11/app/#/phones è ansible visualizzare l’elenco dei telefoni. Se scorri verso il basso e fai clic su una delle ultime, puoi vedere che lo scroll non è in alto, ma è piuttosto nel mezzo.

Ho trovato questo anche in una delle mie app e mi stavo chiedendo come posso farlo scorrere verso l’alto. Posso farlo manualmente, ma penso che ci dovrebbe essere un altro modo elegante per fare ciò che non conosco.

Quindi, c’è un modo elegante per scorrere verso l’alto quando il percorso cambia?

Il problema è che il tuo ngView mantiene la posizione di scorrimento quando carica una nuova vista. Puoi $anchorScroll a $anchorScroll di “scorrere la finestra dopo che la vista è stata aggiornata” (i documenti sono un po ‘vaghi, ma scorrere qui significa scorrere fino alla cima della nuova vista).

La soluzione è aggiungere autoscroll="true" al tuo elemento ngView:

 

Basta inserire questo codice per l’esecuzione

 $rootScope.$on("$routeChangeSuccess", function (event, currentRoute, previousRoute) { window.scrollTo(0, 0); }); 

Questo codice ha funzionato benissimo per me .. Spero che funzionerà anche per te .. Tutto ciò che devi fare è solo iniettare $ anchorScroll sul tuo blocco di esecuzione e applicare la funzione listener al rootScope come ho fatto nell’esempio seguente ..

  angular.module('myAngularApp') .run(function($rootScope, Auth, $state, $anchorScroll){ $rootScope.$on("$locationChangeSuccess", function(){ $anchorScroll(); }); 

Ecco l’ordine di chiamata del modulo Angularjs:

  1. app.config()
  2. app.run()
  3. directive's compile functions (if they are found in the dom)
  4. app.controller()
  5. directive's link functions (again, if found)

RUN BLOCK viene eseguito dopo che l’injector è stato creato e utilizzato per avviare l’applicazione. Significa che quando si è reindirizzato alla nuova vista di route, il listener nel blocco di esecuzione richiama il

$ AnchorScroll ()

e ora puoi vedere lo scroll che inizia in alto con la nuova vista routed 🙂

Dopo un’ora o due di tentativi di ogni combinazione di ui-view autoscroll=true , $stateChangeStart , $locationChangeStart , $uiViewScrollProvider.useAnchorScroll() , $provide('$uiViewScroll', ...) , e molti altri, I couldn ‘ t per scorrere verso l’alto su una nuova pagina per funzionare come previsto.

Questo alla fine è stato ciò che ha funzionato per me. Cattura pushState e replaceState e aggiorna solo la posizione di scorrimento quando si naviga su nuove pagine (il pulsante Indietro / Avanti mantiene le posizioni di scorrimento):

 .run(function($anchorScroll, $window) { // hack to scroll to top when navigating to new URLS but not back/forward var wrap = function(method) { var orig = $window.window.history[method]; $window.window.history[method] = function() { var retval = orig.apply(this, Array.prototype.slice.call(arguments)); $anchorScroll(); return retval; }; }; wrap('pushState'); wrap('replaceState'); }) 

Ecco la mia (apparentemente) robusta, completa e (abbastanza) concisa soluzione. Usa lo stile di minificazione compatibile (e l’accesso angular.module (NAME) al tuo modulo).

 angular.module('yourModuleName').run(["$rootScope", "$anchorScroll" , function ($rootScope, $anchorScroll) { $rootScope.$on("$locationChangeSuccess", function() { $anchorScroll(); }); }]); 

PS Ho trovato che la funzione di autoscatto non ha avuto alcun effetto se impostata su true o false.

Usando angularjs UI Router, quello che sto facendo è questo:

  .state('myState', { url: '/myState', templateUrl: 'app/views/myState.html', onEnter: scrollContent }) 

Con:

 var scrollContent = function() { // Your favorite scroll method here }; 

Non fallisce mai su nessuna pagina e non è globale.

FYI per chiunque incontri il problema descritto nel titolo (come ho fatto io) che sta usando anche il plugin AngularUI Router

Come richiesto e risposto in questa domanda SO, il router angular-ui salta in fondo alla pagina quando si cambiano le rotte.
Non riesci a capire perché i carichi di pagina in fondo? Problema di autoscavimento UI-Router angular

Tuttavia, come afferma la risposta, puoi distriggersre questo comportamento dicendo autoscroll="false" sulla tua ui-view .

Per esempio:

 

http://angular-ui.github.io/ui-router/site/#/api/ui.router.state.directive:ui-view

puoi usare questo javascript

 $anchorScroll() 

Se usi ui-router puoi usare (in esecuzione)

 $rootScope.$on("$stateChangeSuccess", function (event, currentState, previousState) { $window.scrollTo(0, 0); }); 

Ho trovato questa soluzione. Se si passa a una nuova vista, la funzione viene eseguita.

 var app = angular.module('hoofdModule', ['ngRoute']); app.controller('indexController', function ($scope, $window) { $scope.$on('$viewContentLoaded', function () { $window.scrollTo(0, 0); }); }); 

L’impostazione di autoScroll su true non ha funzionato per me, quindi ho scelto un’altra soluzione. Ho creato un servizio che si aggancia ogni volta che il percorso cambia e che utilizza il servizio $ anchorScroll incorporato per scorrere verso l’alto. Per me va bene :-).

Servizio:

  (function() { "use strict"; angular .module("mymodule") .factory("pageSwitch", pageSwitch); pageSwitch.$inject = ["$rootScope", "$anchorScroll"]; function pageSwitch($rootScope, $anchorScroll) { var registerListener = _.once(function() { $rootScope.$on("$locationChangeSuccess", scrollToTop); }); return { registerListener: registerListener }; function scrollToTop() { $anchorScroll(); } } }()); 

Registrazione:

 angular.module("mymodule").run(["pageSwitch", function (pageSwitch) { pageSwitch.registerListener(); }]); 

Tutte le risposte sopra riportate interrompono il comportamento del browser previsto. Ciò che la maggior parte delle persone desidera è qualcosa che scorrerà verso l’alto se è una pagina “nuova”, ma tornerà alla posizione precedente se ci si arriva attraverso il pulsante Indietro (o Avanti).

Se si assume la modalità HTML5, questo risulta essere facile (anche se sono sicuro che alcune persone brillanti là fuori possono capire come renderlo più elegante!):

 // Called when browser back/forward used window.onpopstate = function() { $timeout.cancel(doc_scrolling); }; // Called after ui-router changes state (but sadly before onpopstate) $scope.$on('$stateChangeSuccess', function() { doc_scrolling = $timeout( scroll_top, 50 ); // Moves entire browser window to top scroll_top = function() { document.body.scrollTop = document.documentElement.scrollTop = 0; } 

Il modo in cui funziona è che il router presume che stia andando verso l’alto, ma ritarda un po ‘per dare al browser la possibilità di finire. Se il browser ci informa che la modifica è dovuta a una navigazione Indietro / Avanti, annulla il timeout e lo scorrimento non si verifica mai.

Ho usato i comandi di document elaborati per scorrere perché voglio passare all’intera parte superiore della finestra. Se vuoi solo far scorrere la tua ui-view , quindi imposta autoscroll="my_var" dove controlli my_var usando le tecniche di cui sopra. Ma penso che molte persone vorrebbero scorrere l’intera pagina se si sta andando alla pagina come “nuova”.

Quanto sopra usa ui-router, sebbene tu possa usare ng-route invece scambiando $routeChangeSuccess per $stateChangeSuccess .

Un po ‘tardi alla festa, ma ho provato ogni ansible metodo, e niente ha funzionato correttamente. Ecco la mia soluzione elegante:

Io uso un controller che governa tutte le mie pagine con ui-router. Mi consente di redirect gli utenti che non sono autenticati o convalidati in una posizione appropriata. La maggior parte delle persone inserisce il proprio middleware nella configurazione della propria app, ma ho richiesto alcune richieste http, quindi un controller globale funziona meglio per me.

Il mio index.html ha il seguente aspetto:

 

Il mio initCtrl.js ha il seguente aspetto:

 angular.module('MyApp').controller('InitCtrl', function($rootScope, $timeout, $anchorScroll) { $rootScope.$on('$locationChangeStart', function(event, next, current){ // middleware }); $rootScope.$on("$locationChangeSuccess", function(){ $timeout(function() { $anchorScroll('top-nav'); }); }); }); 

Ho provato ogni opzione ansible, questo metodo funziona al meglio.

Nessuna delle risposte fornite ha risolto il mio problema. Sto usando un’animazione tra le visualizzazioni e lo scorrimento avverrà sempre dopo l’animazione. La soluzione che ho trovato in modo che lo scorrimento verso l’alto avvenga prima dell’animazione è la seguente direttiva:

 yourModule.directive('scrollToTopBeforeAnimation', ['$animate', function ($animate) { return { restrict: 'A', link: function ($scope, element) { $animate.on('enter', element, function (element, phase) { if (phase === 'start') { window.scrollTo(0, 0); } }) } }; }]); 

L’ho inserito sulla mia vista come segue:

 

Prova questo http://ionicframework.com/docs/api/service/ $ ionicScrollDelegate /

Scorre fino alla cima dell’elenco scrollTop ()

Finalmente ho ottenuto ciò di cui avevo bisogno.

Avevo bisogno di scorrere fino in cima, ma volevo che alcune transizioni non lo facessero

Puoi controllarlo a livello di rotta per rotta.
Sto combinando la soluzione di cui sopra con @wkonkel e aggiungendo un semplice noScroll: true parametro noScroll: true per alcune dichiarazioni di percorso. Allora lo sto prendendo nella transizione.

Tutto sumto: questo passa alla parte superiore della pagina su nuove transizioni, non fluttua verso l’alto sulle transizioni Forward / Back e consente, se necessario, di sovrascrivere questo comportamento.

Il codice: (soluzione precedente più un’opzione noScroll extra)

  // hack to scroll to top when navigating to new URLS but not back/forward let wrap = function(method) { let orig = $window.window.history[method]; $window.window.history[method] = function() { let retval = orig.apply(this, Array.prototype.slice.call(arguments)); if($state.current && $state.current.noScroll) { return retval; } $anchorScroll(); return retval; }; }; wrap('pushState'); wrap('replaceState'); 

Metti questo nel tuo blocco app.run e inietta $statemyApp.run(function($state){...})

Quindi, se non vuoi scorrere in cima alla pagina, crea una rotta come questa:

 .state('someState', { parent: 'someParent', url: 'someUrl', noScroll : true // Notice this parameter here! }) 

Questo ha funzionato per me, incluso lo scorrimento automatico