私は、経路が変わるときに、少なくとも私にとっては望ましくない動作を見つけました。チュートリアルのステップ11 http://angular.github.io/angular-phonecat/step-11/app /#/phones 電話のリストを見なさい。一番下までスクロールして最新のものをクリックすると、スクロールが一番上には表示されず、中央に表示されます。
私は自分のアプリの1つでもこれを見つけましたが、どうやってこれを一番上までスクロールさせることができるのか疑問に思いました。私はそれを手動で行うことができますが、これを行うための他のエレガントな方法があるべきだと私は思いますが、私は知りません。
それで、ルートが変わったときに上にスクロールするための優雅な方法はありますか?
問題は、ngViewが新しいビューをロードしたときにスクロール位置を保持することです。 $anchorScroll
に "ビューが更新された後にビューポートをスクロールする"ように指示することができます( ドキュメント は少しあいまいですが、ここでスクロールすると新しいビューの最上部までスクロールします。
解決策はあなたのngView要素にautoscroll="true"
を追加することです。
<div class="ng-view" autoscroll="true"></div>
このコードを実行するだけで
$rootScope.$on("$routeChangeSuccess", function (event, currentRoute, previousRoute) {
window.scrollTo(0, 0);
});
このコードは私にとってはうまくいきました。それがあなたにとってもうまくいくことを私は願っています。
angular.module('myAngularApp')
.run(function($rootScope, Auth, $state, $anchorScroll){
$rootScope.$on("$locationChangeSuccess", function(){
$anchorScroll();
});
Angularjsモジュールの呼び出し順序は次のとおりです。
app.config()
app.run()
directive's compile functions (if they are found in the dom)
app.controller()
directive's link functions (again, if found)
RUN BLOCKは、インジェクタが作成された後に実行され、アプリケーションのキックスタートに使用されます。つまり、新しいルートビューにリダイレクトされると、実行ブロックは
$ anchorScroll()
これで、スクロールが新しいルーテッドビューで上から始まります。
ui-view autoscroll=true
、$stateChangeStart
、$locationChangeStart
、$uiViewScrollProvider.useAnchorScroll()
、$provide('$uiViewScroll', ...)
、およびその他多くの組み合わせを試して1〜2時間経った後、期待どおりに新しいページの上にスクロールすることができませんでした。
これは最終的に私のために働いたものでした。 pushStateとreplaceStateをキャプチャし、新しいページに移動したときにのみスクロール位置を更新します(戻る/進むボタンはそれぞれのスクロール位置を保持します)。
.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');
})
これは私の(一見)堅牢で完全かつ(かなり)簡潔な解決策です。それは縮小互換スタイル(そしてあなたのモジュールへのangular.module(NAME)アクセス)を使用します。
angular.module('yourModuleName').run(["$rootScope", "$anchorScroll" , function ($rootScope, $anchorScroll) {
$rootScope.$on("$locationChangeSuccess", function() {
$anchorScroll();
});
}]);
PS私は、autoscrollがtrueかfalseに設定されていても効果がないことを発見しました。
Angularjs UIルーターを使用して、私がやっているのはこれです:
.state('myState', {
url: '/myState',
templateUrl: 'app/views/myState.html',
onEnter: scrollContent
})
と:
var scrollContent = function() {
// Your favorite scroll method here
};
どのページでも失敗することはなく、グローバルではありません。
Angular UIルーター ( - === - )プラグイン...
このSO質問で尋ねられて答えたように、route-uiルーターはあなたがルートを変更するとページの一番下にジャンプします。
ページが一番下に表示される理由がわかりませんか。 Angular UIルーターの自動スクロールの問題
しかし、答えが述べているように、あなたはあなたのautoscroll="false"
にui-view
を言うことによってこの振る舞いを止めることができます。
例えば:
<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
あなたはこのJavaScriptを使用することができます
$anchorScroll()
あなたは(実行時に)あなたが使用することができますUIルータを使用する場合
$rootScope.$on("$stateChangeSuccess", function (event, currentState, previousState) {
$window.scrollTo(0, 0);
});
私はこの解決策を見つけました。新しいビューに移動すると、関数が実行されます。
var app = angular.module('hoofdModule', ['ngRoute']);
app.controller('indexController', function ($scope, $window) {
$scope.$on('$viewContentLoaded', function () {
$window.scrollTo(0, 0);
});
});
パーティーには少し遅れましたが、可能な限りの方法を試してみましたが、何も正しく機能しませんでした。これが私のエレガントな解決策です。
私はすべてのページを管理するコントローラをui-routerで使用しています。認証も検証もされていないユーザーを適切な場所にリダイレクトできます。ほとんどの人はミドルウェアを自分のアプリの設定に入れていますが、私はいくつかのhttpリクエストを必要としていました。そのため、グローバルコントローラが私にとってはより良く機能します。
私のindex.htmlはこんな感じです:
<main ng-controller="InitCtrl">
<nav id="top-nav"></nav>
<div ui-view></div>
</main>
私のinitCtrl.jsはこんな感じです:
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');
});
});
});
私はすべての可能な選択肢を試してみました、この方法は最もうまくいきます。
AutoScrollをtrueに設定しても私にはうまくいきませんでしたので、別の解決策を選びました。私はルートが変わるたびにフックするサービスを作りました、そしてそれは一番上にスクロールするために組み込みの$ anchorScrollサービスを使います。私のために働きます:-)。
サービス:
(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();
}
}
}());
登録:
angular.module("mymodule").run(["pageSwitch", function (pageSwitch) {
pageSwitch.registerListener();
}]);
提供された答えのどれも私の問題を解決しませんでした。ビュー間でアニメーションを使用していますが、スクロールは常にアニメーションの後に行われます。私が見つけた解決策は、アニメーションの前に一番上までスクロールすることが次のディレクティブであることです。
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);
}
})
}
};
}]);
私の意見では、次のように挿入しました。
<div scroll-to-top-before-animation>
<div ng-view class="view-animation"></div>
</div>
上記のすべての答えは予想されるブラウザの動作を壊します。ほとんどの人が望むのは、それが「新しい」ページの場合は上にスクロールするが、[戻る](または[進む])ボタンを使用して移動した場合は前の位置に戻るものです。
あなたがHTML5モードを想定しているなら、これは簡単であることがわかります(けれども、これをもっと優雅にする方法を考え出すことができると確信している人もいますが!)
// 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;
}
それが動作する方法は、ルーターはそれが一番上にスクロールすることを想定していますが、ブラウザが終了する機会を与えるために少し遅れることです。ブラウザが変更が「戻る/進む」ナビゲーションによるものであることを通知した場合、タイムアウトはキャンセルされ、スクロールは発生しません。
ウィンドウの上部全体に移動したいので、スクロールに生のdocument
コマンドを使用しました。 ui-view
をスクロールさせたいだけの場合は、上記の手法を使用してautoscroll="my_var"
を制御する場所にmy_var
を設定します。しかし、私があなたが "new"としてページに行くのであれば、ほとんどの人はページ全体をスクロールしたいと思うでしょう。
上記ではui-routerを使用していますが、代わりに$routeChangeSuccess
for$stateChangeSuccess
を交換することでng-routeを使用できます。
単純な解決策として、有効にされたメインルートモジュールにscrollPositionRestoration
を追加します。
このような:
const routes: Routes = [
{
path: 'registration',
loadChildren: () => RegistrationModule
},
];
@NgModule({
imports: [
RouterModule.forRoot(routes,{scrollPositionRestoration:'enabled'})
],
exports: [
RouterModule
]
})
export class AppRoutingModule { }
試してください http://ionicframework.com/docs/api/service/ $ionicScrollDelegate /
リストの一番上までスクロールします。scrollTop()
これは自動スクロールを含む私のために働きました
<div class="ngView" autoscroll="true" >
私はようやく必要なものを手に入れました。
一番上までスクロールする必要がありましたが、いくつかの遷移がにならないようにしました
これはルートごとに制御できます。
@wkonkelによる上記の解決策を組み合わせて、いくつかのルート宣言に単純なnoScroll: true
パラメータを追加しています。それから私は移行中にそれを捉えています。
全体として:これは新しいトランジションではページの一番上に浮かぶが、Forward
/Back
のトランジションでは一番上に浮かぶことはなく、必要に応じてこの動作をオーバーライドすることができる。
コード:(以前のソリューションと追加の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');
それをapp.run
ブロックに入れ、$state
...を注入します。myApp.run(function($state){...})
次に、ページの一番上までスクロールしたくない場合は、次のようなルートを作成してください。
.state('someState', {
parent: 'someParent',
url: 'someUrl',
noScroll : true // Notice this parameter here!
})