[解決済み】Angular 2 ルート変更時に上部にスクロールさせる
質問
Angular 2のアプリで、ページをスクロールしてページ下部のリンクをクリックすると、ルートが変更されて次のページに移動しますが、ページの上部にはスクロールしません。その結果、1ページ目が長く、2ページ目のコンテンツが少ない場合、2ページ目のコンテンツが不足しているような印象を与えてしまうのです。コンテンツは、ユーザーがページの一番上までスクロールした場合にのみ表示されるからです。
コンポーネントの ngInit でウィンドウをページトップにスクロールさせることはできますが、アプリ内のすべてのルートを自動的に処理できる、よりよい解決策はありますか?
解決方法は?
Angular 6.1 以降 :
Angular 6.1(2018-07-25リリース)では、"Router Scroll Position Restoration"という機能により、この問題を処理するための組み込みサポートが追加されました。公式で説明されているように アングラーブログ というように、ルーターの設定で有効にするだけです。
RouterModule.forRoot(routes, {scrollPositionRestoration: 'enabled'})
さらに、ブログには "将来のメジャーリリースでこれがデフォルトになることが期待される" と書かれています。今のところ(Angular 11.0時点では)そうなっていませんが、いずれはコードで何もする必要がなくなり、そのまま正しく動作するようになるでしょう。
この機能の詳細と、この動作をカスタマイズする方法については、以下のサイトを参照してください。 公式ドキュメント .
Angular 6.0およびそれ以前 :
GuilhermeMeireles さんの素晴らしい回答は、元の問題を修正する一方で、(ブラウザのボタンやコード内の位置情報を使って)戻る、進むに移動するときに期待される通常の動作を壊して、新しい問題を導入しています。期待される動作は、ページに戻るときに、リンクをクリックしたときと同じ位置までスクロールしたままになることですが、すべてのページに到着したときに一番上までスクロールすることは、明らかにこの期待を裏切るものです。
以下のコードでは、Location の PopStateEvent シーケンスをサブスクライブして、新しく到着したページがそのようなイベントの結果である場合、scroll-to-top ロジックをスキップすることで、この種のナビゲーションを検出するロジックを拡張しています。
しかし、@JordanNelson が正しく指摘したように、ページが短い場合は、元の y スクロール位置を追跡し、ページに戻るときに明示的にそれを復元する必要があります。更新されたバージョンのコードでは、常に明示的にスクロール位置を復元することで、このケースもカバーしています。
import { Component, OnInit } from '@angular/core';
import { Router, NavigationStart, NavigationEnd } from '@angular/router';
import { Location, PopStateEvent } from "@angular/common";
@Component({
selector: 'my-app',
template: '<ng-content></ng-content>',
})
export class MyAppComponent implements OnInit {
private lastPoppedUrl: string;
private yScrollStack: number[] = [];
constructor(private router: Router, private location: Location) { }
ngOnInit() {
this.location.subscribe((ev:PopStateEvent) => {
this.lastPoppedUrl = ev.url;
});
this.router.events.subscribe((ev:any) => {
if (ev instanceof NavigationStart) {
if (ev.url != this.lastPoppedUrl)
this.yScrollStack.push(window.scrollY);
} else if (ev instanceof NavigationEnd) {
if (ev.url == this.lastPoppedUrl) {
this.lastPoppedUrl = undefined;
window.scrollTo(0, this.yScrollStack.pop());
} else
window.scrollTo(0, 0);
}
});
}
}
関連
-
[解決済み】「ルーターリンク」は既知のプロパティではないため、バインドできない
-
[解決済み] Electron - ローカルリソースのロードが許可されていません
-
[解決済み] ag-gridで「表示する行がありません」テキストをプログラムで変更するにはどうすればよいですか?
-
[解決済み] ionInputとionChangeで有意差あり
-
[解決済み] エラーです。参照または変数に代入できません! Angular 4 [重複]の場合
-
[解決済み] Angular HTMLバインディング
-
[解決済み] 現在のルートを取得する方法
-
[解決済み] Angularでは、アクティブなルートをどのように決定するのですか?
-
[解決済み】Angularの例外。ngForIn'は既知のネイティブプロパティではないため、バインドできない
-
[解決済み】Angularでルート変更を検出する方法は?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】angular 4アプリにReactiveFormsModuleを追加すると、NgControl用のプロバイダがないエラーが発生する。
-
[解決済み] Angular 5 Routeクリック毎にトップにスクロールする。
-
[解決済み] チョキダーからのエラー(C:┣ᴗ┣)。Error: EBUSY: resource busy or locked, lstat 'C:\DumpStack.log.tmp.
-
[解決済み] <selector>' が Angular コンポーネントの場合、それがこのモジュールの一部であることを確認する。
-
[解決済み] ng serve または firebase serve を終了させる方法
-
[解決済み] Typescript - コードが TS1128: Declaration or Statement expected というエラーでビルドに失敗するが、コードを提供すると期待通りに実行される。
-
[解決済み] typescriptを使用して、同じhtml DOM要素で「シングルクリック」と「ダブルクリック」を処理する方法:Angular 2または4?
-
[解決済み] プロパティ 'json' はタイプ 'Object' に存在しません。
-
[解決済み] Angular2: [(ngModel)] with [ngModelOptions]="{standalone: true}"を使って、モデルのプロパティへの参照にリンクさせる。
-
[解決済み] AngularでKendo Tabstripのタブを閉じるボタンを実装する方法