wake-up-neo.com

Das Ändern der Route führt auf der neuen Seite nicht zum Anfang

Ich habe ein unerwünschtes Verhalten gefunden, zumindest für mich, wenn sich die Route ändert ... In Schritt 11 des Tutorials http://angular.github.io/angular-phonecat/step-11/app/ #/phones Sie können die Liste der Telefone sehen. Wenn Sie nach unten scrollen und auf eine der letzten klicken, können Sie sehen, dass die Bildlaufleiste nicht oben ist, sondern in der Mitte.

Ich habe dies auch in einer meiner Apps gefunden, und ich habe mich gefragt, wie ich dazu kommen kann, nach oben zu scrollen. Ich kann es auf verschiedene Weise tun, aber ich denke, dass es einen anderen eleganten Weg geben sollte, den ich nicht kenne.

Gibt es eine elegante Möglichkeit, bei Änderungen der Route nach oben zu scrollen?

267
Matias Gonzalez

Das Problem ist, dass Ihr ngView die Bildlaufposition beibehält, wenn eine neue Ansicht geladen wird. Sie können $anchorScroll anweisen, "das Ansichtsfenster nach dem Aktualisieren der Ansicht zu scrollen" (die docs sind etwas vage, aber das Scrollen hier bedeutet, dass zum oberen der neuen Ansicht scrollen).

Die Lösung besteht darin, autoscroll="true" zu Ihrem ngView-Element hinzuzufügen:

<div class="ng-view" autoscroll="true"></div>
574
Konrad Kiss

Setzen Sie einfach diesen Code zur Ausführung

$rootScope.$on("$routeChangeSuccess", function (event, currentRoute, previousRoute) {

    window.scrollTo(0, 0);

});
44
xmaster

Dieser Code hat bei mir großartig funktioniert. Ich hoffe, er funktioniert auch bei Ihnen. Sie müssen nur $ anchorScroll in Ihren Ausführungsblock einfügen und die Listener-Funktion auf das rootScope anwenden, wie ich es im folgenden Beispiel getan habe.

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

Hier ist die Aufrufreihenfolge von Angularjs Module:

  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 wird ausgeführt, nachdem der Injektor erstellt wurde, und wird zum Kickstart der Anwendung verwendet. Dies bedeutet, dass der Listener im Run Block den aufruft, wenn Sie zur neuen Routenansicht umgeleitet werden

$ anchorScroll ()

und Sie können jetzt sehen, dass die Schriftrolle mit der neuen Routing-Ansicht nach oben beginnt :)

36
Rizwan Jamal

Nach ein oder zwei Stunden, in denen ich jede Kombination aus ui-view autoscroll=true, $stateChangeStart, $locationChangeStart, $uiViewScrollProvider.useAnchorScroll(), $provide('$uiViewScroll', ...) und vielen anderen ausprobierte, konnte ich die Scroll-to-top-on-new-page nicht wie erwartet ausführen.

Dies hat letztendlich für mich funktioniert. Es erfasst pushState und replaceState und aktualisiert die Bildlaufposition nur, wenn zu neuen Seiten navigiert wird (die Vor-/Zurück-Schaltfläche behält ihre Bildlaufpositionen):

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

Hier ist meine (scheinbar) robuste, vollständige und (ziemlich) prägnante Lösung. Es verwendet den Minification-kompatiblen Stil (und den angle.module (NAME) Zugriff auf Ihr Modul).

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

PS: Ich fand heraus, dass das Autoscroll-Ding keine Auswirkung hatte, egal ob es auf true oder false gesetzt war.

18
James

Ich verwende den anglejs UI Router.

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

Mit:

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

Es versagt nie auf einer Seite und ist nicht global.

15
Léon Pelletier

FYI für alle, die auf das im Titel beschriebene Problem stoßen (wie ich es getan habe), der auch das AngularUI Router -Plugin verwendet.

Wie in dieser SO Frage gefragt und beantwortet, springt der eckige-ui-Router beim Wechseln der Routen zum unteren Rand der Seite.
Kann nicht herausfinden, warum die Seite unten geladen wird? Angular UI-Router Autoscroll Ausgabe

Wie die Antwort sagt, können Sie dieses Verhalten jedoch deaktivieren, indem Sie autoscroll="false" in Ihrem ui-view angeben. 

Zum Beispiel: 

<div ui-view="pagecontent" autoscroll="false"></div>
<div ui-view="sidebar" autoscroll="false"></div> 

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

13
mg1075

sie können dieses Javascript verwenden

$anchorScroll()
7
CodeIsLife

Wenn Sie einen ui-router verwenden, können Sie (on run)

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

Ich habe diese Lösung gefunden. Wenn Sie zu einer neuen Ansicht wechseln, wird die Funktion ausgeführt.

var app = angular.module('hoofdModule', ['ngRoute']);

    app.controller('indexController', function ($scope, $window) {
        $scope.$on('$viewContentLoaded', function () {
            $window.scrollTo(0, 0);
        });
    });
4
Vince Verhoeven

Ein bisschen zu spät zur Party, aber ich habe jede mögliche Methode ausprobiert und nichts hat richtig funktioniert. Hier ist meine elegante Lösung:

Ich verwende einen Controller, der alle meine Seiten mit dem UI-Router verwaltet. Dadurch kann ich Benutzer, die nicht authentifiziert oder validiert wurden, an einen geeigneten Ort umleiten. Die meisten Leute fügen ihre Middleware in die Konfiguration ihrer App ein, aber ich benötigte einige HTTP-Anforderungen. Daher funktioniert ein globaler Controller besser für mich.

Meine index.html sieht folgendermaßen aus:

<main ng-controller="InitCtrl">
    <nav id="top-nav"></nav>
    <div ui-view></div>
</main>

Meine initCtrl.js sieht folgendermaßen aus:

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

Ich habe jede mögliche Option ausprobiert, diese Methode funktioniert am besten.

3
BuffMcBigHuge

Die Einstellung von autoScroll auf true war für mich nicht der Trick, also habe ich eine andere Lösung gewählt. Ich habe einen Dienst erstellt, der bei jeder Änderung der Route eine Verbindung herstellt und der integrierte AnchorScroll-Dienst verwendet, um nach oben zu scrollen. Funktioniert bei mir :-).

Bedienung:

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

Anmeldung:

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

Keine der Antworten löste mein Problem. Ich verwende eine Animation zwischen Ansichten und das Scrollen würde immer nach der Animation erfolgen. Die Lösung, die ich gefunden habe, damit das Scrollen nach oben vor der Animation geschieht, ist die folgende Anweisung:

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

            })
        }
    };
}]);

Ich habe es wie folgt in meine Ansicht eingefügt: 

<div scroll-to-top-before-animation>
    <div ng-view class="view-animation"></div>
</div>
2
aBertrand

Alle obigen Antworten beeinträchtigen das erwartete Browserverhalten. Die meisten Leute wünschen sich etwas, das nach oben scrollen kann, wenn es sich um eine "neue" Seite handelt, aber zur vorherigen Position zurückkehren, wenn Sie mit der Zurück- (oder Vorwärts-) Taste dorthin gelangen.

Wenn Sie den HTML5-Modus annehmen, stellt sich dies als einfach heraus (obwohl ich mir sicher bin, dass einige kluge Leute herausfinden können, wie man dies eleganter macht!):

// 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;
}

Die Funktionsweise besteht darin, dass der Router davon ausgeht, dass er nach oben scrollen wird, sich jedoch etwas verzögert, damit der Browser die Möglichkeit hat, den Vorgang abzuschließen. Wenn der Browser uns dann mitteilt, dass die Änderung auf einer Vorwärts-/Rückwärtsnavigation beruht, bricht der Timeout ab und die Bildlauffunktion tritt nie auf.

Ich habe rohe document-Befehle zum Scrollen verwendet, weil ich zum gesamten oberen Fensterbereich wechseln möchte. Wenn Sie nur möchten, dass Ihr ui-view einen Bildlauf durchführt, legen Sie autoscroll="my_var" fest, wo Sie my_var mit den oben beschriebenen Verfahren steuern. Ich denke jedoch, dass die meisten Leute die gesamte Seite scrollen möchten, wenn Sie als "neu" auf die Seite gehen.

Das obige verwendet ui-router, obwohl Sie stattdessen ng-route verwenden können, indem Sie $routeChangeSuccess durch$stateChangeSuccess austauschen.

2
Dev93

Einfache Lösung, fügen Sie scrollPositionRestoration im aktivierten Hauptroutenmodul hinzu.
So was:

const routes: Routes = [

 {
   path: 'registration',
   loadChildren: () => RegistrationModule
},
];

 @NgModule({
  imports: [
   RouterModule.forRoot(routes,{scrollPositionRestoration:'enabled'})
  ],
 exports: [
 RouterModule
 ]
 })
  export class AppRoutingModule { }
1
Farida Anjum

Probieren Sie diese http://ionicframework.com/docs/api/service/ $ ionicScrollDelegate /

Es blättert an den Anfang der Liste. ScrollTop ()

0
ToughPal

Dies funktionierte für mich inklusive Autoscroll

<div class="ngView" autoscroll="true" >

0
Teja

Ich habe endlich das bekommen, was ich brauchte.

Ich musste nach oben scrollen, wollte aber einige Übergänge nicht zu  

Sie können dies auf einer Route für Route steuern.
Ich kombiniere die obige Lösung von @wkonkel und füge einigen Routendeklarationen einen einfachen noScroll: true-Parameter hinzu. Dann fange ich das im Übergang auf. 

Alles in allem: Dies schwebt bei neuen Übergängen ganz oben auf der Seite, bei Forward/Back-Übergängen nicht ganz oben und ermöglicht es Ihnen, dieses Verhalten bei Bedarf außer Kraft zu setzen.

Der Code: (vorherige Lösung plus eine zusätzliche Option noScroll)

  // 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');

Fügen Sie das in Ihren app.run-Block ein und injizieren Sie $state... myApp.run(function($state){...})

Wenn Sie nicht zum Anfang der Seite blättern möchten, erstellen Sie eine Route wie folgt:

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