Angular: ルートを変更しても、新しいページの一番上にスクロールしません

作成日 2016年03月28日  ·  103コメント  ·  ソース: angular/angular

あるルートから別のルートに移動してから少し下にスクロールして前のルートに戻ると、ページは同じスクロール位置のままになります。

現在の動作

あるビューから別のビューに移動してから、少し下にスクロールして前のビューに戻ります。 ページは同じスクロール位置のままです。

期待される/望ましい動作

別のルートに戻るときは、ページを一番上までスクロールする必要があります。

router feature high google obvious

最も参考になるコメント

ルートルーターの変更でのみトップになりたい場合があります(タブセットで遅延ロードを使用してルートをロードできるため、子ではありません)

それを解決する別の方法:

<router-outlet (deactivate)="onDeactivate()"></router-outlet>
onDeactivate() {
    document.body.scrollTop = 0;
}

全てのコメント103件

#6595の重複?

#6595の重複?

そうは思いません。

6946は回避策を示しています

期待される/望ましい動作

別のルートに戻るときは、ページを一番上までスクロールする必要があります。

それは私にとって予期された振る舞いではありません。 私に期待される動作は次のとおりです。

別のルートに戻るときは、ページを先に進む前の位置までスクロールする必要があります。 これは、通常のページ(SPAではない)間を移動するときにすべてのブラウザーに現在実装されている動作です。 しかし、angular1ルーターの実装ではこの動作は見られませんでした。

リストを下にスクロールし、リストアイテムをクリックして詳細ページを表示し、詳細を下にスクロールしてから、ブラウザのBackボタンをクリックすると、以前とまったく同じ状態のリストページが表示されないのは非常に面倒です。

  • まったくスクロールしない場合:リストページのランダムなスクロール位置になります。
  • 一番上までスクロールする場合:良いですが、常にリストページの一番上に表示されますが、「通常の」サイト(SPAではない)では、詳細ページに移動する前のスクロール位置に表示されます。

たとえば、githubはこれを正しく実装しています。問題リストを開いて下にスクロールし、問題の詳細を開いてから、 Backブラウザボタンをクリックします。 問題の詳細ページを開く前とまったく同じスクロール位置になります。

angle2ルーターがそれを行うことができればそれは非常にクールです。 これは、他のルーターでは見たことのないキラー機能です。

編集
現在、この動作には専用の問題がありますhttps://github.com/angular/angular/issues/10929

このデフォルトのスクロール動作を変更するには、属性またはパラメータを設定したほうがよい場合がありますか?

RC.4で一番上までスクロールするための推奨される方法はありますか? #6946で提案された回避策は機能しなくなりました。

@andyrueこれはお勧めできないと思いますが、#6946に更新を投稿しました

私の場合、 window.scrollTo(0, 0)トリックは機能しません。これは、実際にはオーバーフローしているルーター出口の一番上までスクロールする必要があるためです。 同様の問題がある場合、これは回避策として私が行ったことです。

@Component({
  template: '<router-outlet (activate)="onActivate($event, outlet)" #outlet></router-outlet>,
})
export class MyParentComponent {
  onActivate(e, outlet){
    outlet.scrollTop = 0;
  }
}

解決策はありますか? 提案されたソリューションはどれも機能しません。
これは私にとってはうまくいっているようです-どのくらいの期間、わかりません:

ngAfterViewChecked(){
window.scrollTo(0、0);
}

@Ariixは、変更検出が実行されるたびにスクロールしませんか?

@Cortopyはい、そうです。 だからまだ探している

このための更新またはマイルストーンはありますか?

これに関する更新はありますか? リストを下にスクロールするときに煩わしいのは、リストアイテムをクリックして、上にスクロールする必要のある詳細(別のルート上にある)を表示することです。 次の詳細ページの長さが短く、リストページが非常に長い場合、偶然にリストの最後の項目をクリックしました。 詳細ページにコンテンツがないという印象を与えます(ユーザーがコンテンツを表示するには上にスクロールする必要があるため)。

@zoechiコメントはハッシュ付きのURLに関するものだと思います。私の場合、ハッシュはありません。

リストページにはURLがあります:
/リスト

詳細ページにはURLがあります:
/ details / 123

@ naveedahmed1まだscrollIntoView()またはscrollTop=0電話できます

@ zoechi-完全なコードを共有できますか? 子ルートが変更されている親子シナリオがあります

私の回避策には、ElementRefクラスが含まれます。

  constructor(
    private route: ActivatedRoute,
    private service: GuideService,
    private router: Router,
    private element: ElementRef
  ) {
    this.scrollUp = this.router.events.subscribe((path) => {
      element.nativeElement.scrollIntoView();
    });
  }

これはどう?

import { Component, OnInit} from '@angular/core';
import { Router, NavigationEnd } from '@angular/router';

@Component({
    moduleId: module.id,
    selector: 'app',
    templateUrl: './app.component.html'
})

export class AppComponent implements OnInit {
    constructor(private router: Router) {}

    ngOnInit() {
        this.router.events.subscribe((evt) => {
            if (!(evt instanceof NavigationEnd)) {
                return;
            }

            var scrollToTop = window.setInterval(function () {
                var pos = window.pageYOffset;
                if (pos > 0) {
                    window.scrollTo(0, pos - 20); // how far to scroll on each step
                } else {
                    window.clearInterval(scrollToTop);
                }
            }, 16); // how fast to scroll (this equals roughly 60 fps)
        });
    }
}
    router.events.filter(event => event instanceof NavigationEnd).subscribe(event => {
        window.scroll(0, 0);
    });

これはスクロール位置を覚えているようですが(ChromeとFirefoxではIEは覚えていません)、理由はわかりません。

@SmaugTheGreatはい、それは機能します! しかし、最後のスクロール位置を記憶している可能性さえありますか?

@SmaugTheGreatソリューション、つまりwindow.scroll(0、0);を使用すると、奇妙なことになります。 スクロール位置を記憶しています。
ただし、window.setIntervalでwindow.scrollを使用すると、スクロール位置は記憶されません。

NavigationEndにルートのパラメータやクエリパラメータなどが含まれていないのはなぜですか? 文字列だけ?

上記のSmaugsソリューションとstackoverflowのGuilhermeMeirelesを組み合わせると、うまくいきます。 また、リークを回避するためにngOnDestroyのサブスクライブを解除します。

import { Component } from '@angular/core'; 
import { Router, NavigationEnd } from '@angular/router'; 
import { Subscription } from 'rxjs/Rx';

@Component({
    moduleId: module.id, 
    selector: ‘my-app’,
    template: `<router-outlet></router-outlet>`
})

export class AppComponent {
    routerSubscription: Subscription;

    constructor(private router: Router) {}

    ngOnInit() {
        this.routerSubscription = this.router.events
            .filter(event => event instanceof NavigationEnd)
            .subscribe(event => {
                document.body.scrollTop = 0;
            });
    }

    ngOnDestroy() {
        this.routerSubscription.unsubscribe();
    }
}

'ng2-page-scroll'モジュールを使用します。 迅速な対応として、コンポーネントの1つを投稿しています。 これは私のために働いた。

import {Component、OnInit、Inject} from '@ angle / core';
import {Router、Route、NavigationEnd} from '@ angle / router';
import {AppSharedService} from '../ app.service';
import {DOCUMENT} from '@ angle / platform-b​​rowser';
'rxjs / Rx'から{サブスクリプション}をインポートします。
import {PageScrollService、PageScrollInstance} from'ng2-page-scroll ';

@成分({
セレクター: 'app-resources'、
templateUrl: './ resources.component.html'、
styleUrls:['./ resources.component.scss']
})
エクスポートクラスResourcesComponent {

routerSubscription:サブスクリプション;

コンストラクター(プライベートルーター:ルーター、プライベートSharedService:AppSharedService、プライベートpageScrollService:PageScrollService、@ Inject(DOCUMENT)プライベートドキュメント:any、){
let pageScrollInstance:PageScrollInstance = PageScrollInstance.simpleInstance(this.document、 '#app-give');
this.pageScrollService.start(pageScrollInstance);

}

}

@shanehickeylk
サブスクリプションを変数に保存するので、サブスクリプションを解除するだけでよいと思います。

router.events ..... .subscribe()を直接呼び出した場合、サブスクライブを解除するサブスクリプションはありません。

更新:はい、そうです:)ごめんなさい

@ spock123
サブスクリプションは、変数に割り当てられていなくても「生きている」と思います。 これは、Angularがイベントがトリガーされたことを知る方法です。 変数に割り当てる理由は、後でアクセスしてサブスクライブを解除できるようにするためです。

これはブライアン・ラブによる良い記事であり、彼はこのトピックに関するいくつかの追加の詳細を説明しています。
http://brianflove.com/2016/12/11/anguar-2-unsubscribe-observables/

8、ありがとう..できるだけ早くいくつかのプロダクションを書き直す必要があります😎😎

ルートルーターの変更でのみトップになりたい場合があります(タブセットで遅延ロードを使用してルートをロードできるため、子ではありません)

それを解決する別の方法:

<router-outlet (deactivate)="onDeactivate()"></router-outlet>
onDeactivate() {
    document.body.scrollTop = 0;
}

ルートリゾルバーを使用するたびにこの問題が発生することを報告したいだけです。 コンポーネントが破壊/ルーターにロードされるタイミングに関係しているようです。 リゾルバーを使用すると、コンポーネントの読み込みが非常に速く、速すぎるようです。ルーターのコンセントが本当に空になることはないので、スクロール位置は前のコンポーネントから保存されます。 ただし、他のすべてのルート/コンポーネントでは、これは問題ではありません

ui-viewにautoscroll = "true"を追加することで、この問題を解決しました

josh81、あなたが言ったことは角度1であり、角度2ではありません

@JoniJnmおそらくレンダラーを使用する方が良いでしょうか?

<router-outlet (deactivate)="onDeactivate()"></router-outlet>

import { Component, Renderer } from '@angular/core';

`` `export class AppComponent {

コンストラクター(プライベートレンダラー:レンダラー){
}

onDeactivate(){
this.renderer.setElementProperty(document.body、 "scrollTop"、0);
}
}
`` `

これをapp.component::ngOnInitに追加して、sidenavコンテンツコンテナにコンテンツが含まれているためにウィンドウまたはドキュメント本文のネイティブスクロールが機能しなかったルーティング後のスクロールの問題を回避しました。 これがbeta.4まで一時的に誰かを助ける場合。

this.router
  .events
  .filter(event => event instanceof NavigationEnd)
  .subscribe(() => {
      const contentContainer = document.querySelector('.mat-sidenav-content') || this.window;
      contentContainer.scrollTo(0, 0);
  });

私はこれを処理する小さなサービスを作成しました:

チュートリアル

ソース

Rendererを使用する@kormicは良い考えです! ただし、 Rendererは非推奨であるため、ここではRenderer2を使用する必要があります。 また、 setElementProperty()に変更されましたsetProperty()Renderer2

私はこれを@kormic@mtpultzの回避策と組み合わせましたが、これは私にとってはかなりうまく機能しているようです。

    this.router.events.filter(event => event instanceof NavigationEnd).subscribe(() => {
      this.renderer.setProperty(document.body, 'scrollTop', 0);
    });

@Splaktar私は角度のあるユニバーサルアプリを持っています。 サーバー例外を回避する方法。
3つの方法は機能しますが、サーバーメッセージがあります:

window.scrollTo(0,0); //ウィンドウが定義されていません。
this.element.nativeElement.scrollIntoView(false); // scrollIntoViewが定義されていません
this.renderer.setProperty(document.body、 'scrollTop'、0); //ドキュメントが定義されていません

1時間の作業の後、最終的にサーバー側のレンダリングの解決策が見つかりました

if (isPlatformBrowser(this.platformId)) {
                var scrollingElement = this.document.scrollingElement || this.document.documentElement;
                this.renderer.setProperty(scrollingElement ,'scrollTop',0);
            }

参考までに、これを気にする人は、おそらく「戻る」をナビゲートするときに前のビューのスクロール位置を保持することも気にします。 それは別の問題#10929にあります。

私の質問は、これを#hashアンカーと組み合わせると、そのままではサポートされておらず、Angularでルーターを10回繰り返した後はわからないということです。

  1. リンクをクリックすると、一番上までスクロールするはずです。
  2. リンクをクリックして#が表示されている場合は、そのページに移動してスクロールするか、同じページの場合は下にスクロールします。
  3. 私が後ろまたは前にぶつかった場合、それは私がいた場所に行くはずです。

これは難しいことではありません。 これは1992年のように解決されたと思いました。Googleの誰かが立ち上がって頭をノックしてください。 これは昨日修正する必要があります。 Lynxが実行できるようになったので、すべてのブラウザーが実行できるようにするためだけにハックを作成する必要はありません。

app.component.ts 、次のコードを追加
this.router.events.filter(event => NavigationEndのイベントインスタンス).subscribe((e:NavigationEnd)=> {
document.body.scrollTop = 0;
});

とりわけ、ページの#表記などでは正しく機能しません。これは、上記の要件に従って、ルートコードのAngularチームによって適切に修正される必要があります。

これは、SPAで期待される動作である必要があります。 私たちは本番アプリの回避策を試していますが、それは実際にはすぐに使えるソリューションであるはずです。

以前のコメントのほとんどに同意します。私のアプリケーションはまだ本番環境にないため、回避策を必要とせずにこれが実装されることを望んでいます。

自動スクロールはFirefoxでは機能しなくなりました:-/
55.0.1(64ビット)

ただし、Chromeは期待どおりに機能します。

これは私のために働く
let number = window.scrollY || window.pageYOffset || document.body.scrollTop + (document.documentElement && document.documentElement.scrollTop || 0)

私のチームは、angular.ioのこのリポジトリ<body>の先頭に追加する必要があります: <div id="top-of-page"></div>

使ったばかり
this.router.navigate(['myNextPage']).then(() => { window.scrollTo(0, 0) });

そしてそれはうまくいった。

繰り返しますが、それはそれがすることになっていることではありません。

通常の古いWebサイトにアクセスして戻るボタンを押すと、元に戻り、クリックしたページの正確な位置が維持されるため、中断したところに正確に戻ります。

Angularにはこれが組み込まれている必要があり、正しく機能する必要があります。 ハッキングや機能の悪い見積もりを提供することはありません。 ユーザーが自動的に期待するとおりに機能する実際の取引。

これをメインコンポーネントに追加するだけです

constructor(private router: Router) {
    this.router.events.subscribe(
      () => window.scrollTo(0, 0)
    );
  }

これは私のために働きます:

<router-outlet (deactivate)="onDeactivate()"></router-outlet>
onDeactivate() {
    window.scrollTo(0, 0);
}

@ JohnGalt1717古いウェブサイトに表示されるものは、ブラウザによって処理されます。 Angularのようなフレームワークではまったく異なります。 Angularは問題を処理するためにjavascriptを利用する必要がありますが、一貫性のあるクリーンなソリューションを得るのは不可能かもしれません。 他のすべてのフレームワークにも同じ問題があります。 そこにある問題を解決する唯一の簡単な方法は、ルートを切り替えるときに要素を破棄するのではなく非表示にすることです。そうすると、ブラウザはスクロール位置の復元を実行します。

@crysislinuxそれは実際にはかなり些細なことです。 戻るボタンをインターセプトして再ナビゲートする履歴バッファでは、スクロール位置も保存する必要があり、戻る/進むが押されると、ngOnInit()が完了した後にその位置にスクロールします。

ただし、すべての(非同期などの)データがまだレンダリングされていない可能性があるため、ngOnInitで正確に実行することはできません。

ngOnInitは非同期(約束)を可能にするので、あなたはそうすることができます。 開発者がそれを正しく行わない場合、それはあなたの問題ではなく、それを間違って行うことに対する彼らの問題です。

デバイスを横向きに回転させた後、画像を含むデータを非同期にロードする可能性のある、ページ上にあるスクロール可能なdivをすべて復元することを考えていただければ幸いです。

これについて些細なことは何もありません...私はこれまで誰もプラグインを思い付かなかったことに驚いています。 あなたはすぐに有名になるでしょう。 それまでの間、一番上までスクロールしてください:-)

(少なくともChromeでは)使いやすさの面から私が得た最善の解決策は、そのように前方ナビゲーションを行う場所でwindow.scrollを手動で実行

this.router.navigate(['/payment']).then(() => {
  window.scroll(0, 0); // should be here, in promise
});

その場合、Chromeは後ろに移動するとスクロール位置を正しく復元し、前に移動すると位置をリセットします(ただし、そうです、どこでも手動で行うか、ナビゲーションのための何らかの独自の方法にラップする必要がありますが、別の解決策は見つかりませんでした)。

app.component.tsファイル内のonDeactivate()関数によってトリガーされた@angular/coreライブラリからRendererオブジェクトをインポートする@kormicのソリューションをブロードキャストするだけで、Angularで引き続き機能します4プロジェクト、 angular-cli @ 4.0.0でビルドされました

私のためのこの仕事:
https://stackoverflow.com/questions/39601026/angular-2-scroll-to-top-on-route-change

コンポーネント内:

import { Component, OnInit } from '@angular/core';
import { Router, NavigationEnd } from '@angular/router';

@Component({
    selector: 'my-app',
    template: '<ng-content></ng-content>',
})
export class MyAppComponent implements OnInit {
    constructor(private router: Router) { }

    ngOnInit() {
        this.router.events.subscribe((evt) => {
            if (!(evt instanceof NavigationEnd)) {
                return;
            }
            window.scrollTo(0, 0)
        });
    }
}

Angular 5にアップグレードしましたが、どれも機能しませんでした。 実際、私のDOM呼び出しはまったく機能していないように見えました(例:window.scrollTo(0、0))。

簡単な解決策は、必要なコンポーネントのngOnInit内にwindow.scrollTo(0,0)を追加することです。
`` `javascript
ngOnInit(){
window.scrollTo(0、0);
}

@ericmartinezrアップデートありがとうございます。 私はAngularMaterial(具体的にはMatSidenav)を使用しているため、ウィンドウとボディへの呼び出しが機能しませんでした。 (たとえば、スクロールできませんでした)。 適切なDOM要素( .mat-sidenav-content )で呼び出すと、すべてが機能しました。 要素bodywindowは、 .mat-sidenav-content親であるため、スクロール可能であると想定しました。

別のルートに戻るときは、ページを先に進む前の位置までスクロールする必要があります。 これは、通常のページ(SPAではない)間を移動するときにすべてのブラウザに現在実装されている動作です。 しかし、angular1ルーターの実装ではこの動作は見られませんでした。

@ xak2000は素晴らしい点を提起しますが、私が見ている動作は、それが「戻る」アクションであるか、まったく新しいページへのナビゲーションであるかに関係なく、スクロール位置が維持されることです。 バックアクションのスクロール位置を維持することは問題ありませんが、新しいページに移動するためのバグのようです。

ありがとう@ naveedahmed1 ; それはとてもうまくいきました

約束の解決が私にとって最良の解決策だったときの@bobrosoftスクロールと同じ

さらにクロームに、それはサファリでも動作します

@ naveedahmed1ありがとう^ _ ^

window.scrollTo()は機能しますが、DOMオブジェクトが存在する場所でユニバーサルを使用するとどうなりますか?

@marticrespiサーバーにはスクロール位置の概念がないため、 scrollToコードをisPlatformBrowserチェックでラップするだけです。

これが私の解決策です...

編集:これは、ルートを変更するときにスクロールバーを一番上にリセットする方法の質問に答えることを述べておかなければなりません。 また、ブラウザの戻るボタンと進むボタンが壊れていないことを確認します。 つまり、戻るまたは進むをクリックすると、スクロールバーは最初にページを離れたときの位置に戻ります。 また、これまでに見た他の回答とは異なり、ブラウザの戻るボタンまたは進むボタンをクリックして押したままにすると、すべてが機能するというエッジケースがあります。 これがお役に立てば幸いです...

      export class AppComponent implements OnInit {
      isPopState = false;

      constructor(private router: Router, private locStrat: LocationStrategy) { }

      ngOnInit(): void {
        this.locStrat.onPopState(() => {
          this.isPopState = true;
        });

        this.router.events.subscribe(event => {
          // Scroll to top if accessing a page, not via browser history stack
          if (event instanceof NavigationEnd && !this.isPopState) {
            window.scrollTo(0, 0);
            this.isPopState = false;
          }

          // Ensures that isPopState is reset
          if (event instanceof NavigationEnd) {
            this.isPopState = false;
          }
        });
      }
    }

@ sal-vaderうまく機能します、ありがとう

それはうまくいきましたありがとう;)

これはまだrc4で壊れています

追加するだけでこの問題を解決しました

constructor(private router: Router) { this.router.events.subscribe( () => window.scrollTo(0, 0) ); }
app.component.ts(私が一番上のルーターアウトレットを持っているところ)では、それだけです

上記のソリューションは多くのデバイスで正常に機能しますが、私が確認したように、モバイルデバイスでは機能しません。 次の解決策は、さまざまな種類のデバイスでこの問題を解決するために使用したものです。 最初に、app.componentのコンストラクターでモバイルデバイスをチェックしました

if(isPlatformBrowser(this.platformId)){
if(window.screen.width <= 1024){
this.mobile = true;
}

そしてngOnInitで

if(isPlatformBrowser(this.platformId)){
this.routerSubscription = this.router.events
.filter(event => NavigationEndのイベントインスタンス)
.subscribe(event => {
if(this.mobile){
const element = document.querySelector( '#scrollId1');
element.scrollIntoView();
} それ以外 {
window.scrollTo(0、0);
}
});
}

また、それらすべてをngOnInitまたはコンストラクターでマージすることもできます。
モバイルデバイスで機能するには、最上部のdivのIDをscrollId1に設定する必要があることに注意してください。

私の場合、上記の解決策が機能していなかったので、コンソールをチェックしたところ、ウィンドウのscrollTo()メソッドが機能していないことがわかったので、ユーザーを0の位置に移動する代わりに、別の解決策を見つけました。ページの0私はscrollIntoView()メソッドを使用して、ページのトップコンポーネント(私の場合はapp-website-nav)をビューに表示し、それが機能します!!!! これで、URLが変更されるたびに、app-website-navコンポーネントがあるページの上部にビューが表示されます。
ここに、シンプルで機能するコードがあります。

import { Router, NavigationEnd } from '@angular/router';
private router: Router,

constructor(private router: Router)

ngOnInit()
   {
     this.router.events.subscribe((evt) => {
                 if (!(evt instanceof NavigationEnd)) {
                     return;
                 }
                 document.getElementsByTagName("app-website-nav")[0].scrollIntoView();
             });
   }

ルーターの変更を伴うスムーズなスクロールのために使用できます

  constructor(private router: Router) {}

  ngOnInit() {
    this.router.events.subscribe(() =>
      window.scrollTo({
        top: 0,
        left: 0,
        behavior: 'smooth'
      })
    );
  }

@ mkhan004興味深いですが、 behaviorはブラウザネイティブの権利ではありません(https://www.w3schools.com/jsref/met_win_scrollto.asp)?

したがって、 window.scrollToなどをオーバーライドする特別なlib / polyfillを使用していますか?

@peterpeterparkerこれはネイティブブラウザの動作です。 アドバイス-W3Schoolsは使用しないでください。不正確または単に間違った情報で知られています。 MDNを使用することをお勧めします。 ここに関連するページ: https

@mgolthx👍

言及する価値があります: behavior: 'smooth'はIEまたはEdgeではサポートされていません。

ただし、ChromeとFirefoxの現在のバージョンは機能しているようです。

@MartinMaそれは良い点です。 関連するCanIUseページはhttps://caniuse.com/#feat=css-scroll-behaviorです

注だけでも、省略することbehavior: 'smooth' 、彼らがするオブジェクト構文サポートしていないとして、まだIE /エッジ/サファリを中断しますscrollTo 、ちょうど位置1: scrollTo(x, y) 。 Chrome / Firefoxでスムーズスクロールとその他の非スムーズスクロールの両方をサポートするには、次のロジックを使用できます(目的のx / y値を使用)。

if ('scrollBehavior' in document.documentElement.style) {
  window.scrollTo({
    behavior: 'smooth',
    left: x,
    top: y,
  });
} else {
  window.scrollTo(x, y);
}

では、この問題を解決するための最良のオプションは何ですか?

https://github.com/angular/angular/pull/20030によって閉じられました

上記のように修正されたことに基づいて終了します。

ngOnitでwindow.scrollTo(0,0);を使用します。 だからそれはこのように見えるはずです
ngOnInit() { window.scrollTo(0,0); }

Angular6.1をご覧ください。 これは修正されており、おそらく将来のリリースではデフォルトになります

これが最善の解決策です!!!

import {Component} from '@ angle / core';
import {Router、NavigationEnd} from '@ angle / router';

@成分({
セレクター: 'sv-app'、
レンプレート: ' '
})
エクスポートクラスAppComponent {

コンストラクター(プライベートルーター:ルーター){

router.events
  .filter(event => event instanceof NavigationEnd)
  .subscribe((event: NavigationEnd) => {
    window.scroll(0, 0);
  });

}
}

回避策は、これをapplication.run()に配置することです-少なくとも古いバージョンのAngularでは。 誰かを助けるかもしれません!

`` `
var interval = setInterval(function(){
if(document.readyState === 'complete'){
$ window.scrollTo(0、0);
clearInterval(interval);
}
}、10);

@JamieFarrellyの公式ソリューションがリリースされました

ルーター:スクロール復元サービス(#20030)(49c5234)を実装し、#13636#10929#7791#6595を閉じます

@ドキュメントを参照してください:

[編集]あなたの場合はそうです:

@NgModule({
  imports: [RouterModule.forRoot(routes, {
    scrollPositionRestoration: 'top'
  })],
  exports: [RouterModule]
})

これはAngularMaterial <mat-sidenav-container fullscreen>では機能しません。これは、スクロールコンテナが<mat-sidenav-content>なり、ドキュメントの本文ではなくなったためだと思います。 これを修正する方法はありますか?

@odahcam MatDrawerContainerを使用していますが、ViewChildでフォームを使用できます

@ViewChild('scroll') myScrollContainer:MatDrawerContainer; 
this.myScrollContainer.scrollable.getElementRef().nativeElement.scrollTop= 0;

ええ、コンテナをスクロールすることはできますが、ルーターに自動的にスクロールさせるにはどうすればよいですか? (ビューポートの場合と同じように)

@odahcam

  <router-outlet (activate)="onActivate($event)"></router-outlet>
onActivate(event){
    this.myScrollContainer.scrollable.getElementRef().nativeElement.scrollTop= 0;
}

または私はあなたを誤解しましたか?

実際、私はそのようなものを使用していますが、 scrollPositionRestoration: 'top'オプションを有効にすると、ビューポートでスクロールしようとして機能しないため、ルーターにはスクロール可能なコンテナー構成が必要だと思います。

あなたのコードは私のものと同じように機能しますが、私たちの両方が私たちのためにスクロールジョブを実行するネイティブルーター機能から利益を得ることができません。 そのためには、ビューポートの代わりにカスタムのスクロール可能なコンテナを使用するようにルーターに指示する必要があります。

ルーターがViewportScrollerという名前の人を利用していることに気付きました。ドキュメントにあるように、スクロール動作をカスタマイズしたくない場合は、モジュールまたはコンポーネントにその人を挿入する必要があります。

class AppModule {
 constructor(router: Router, viewportScroller: ViewportScroller, store: Store<AppState>) {
   router.events.pipe(filter(e => e instanceof Scroll), switchMap(e => {
     return store.pipe(first(), timeout(200), map(() => e));
   }).subscribe(e => {
     if (e.position) {
       viewportScroller.scrollToPosition(e.position);
     } else if (e.anchor) {
       viewportScroller.scrollToAnchor(e.anchor);
     } else {
       viewportScroller.scrollToPosition([0, 0]);
     }
   });
 }
}

フルスクリーンのcdkContainerようなものをルーターのスクロール復元に統合する唯一の方法は、自分のViewportScrollerを実装し、Angularがルーターに使用する注入トークンを変更してデフォルトの代わりにスクローラー。

残念ながら、この問題に関するドキュメントは少し存在しないため、事態はさらに困難になります。

Angular 6.1以降:

RouterModule.forRoot(routes、{scrollPositionRestoration: 'enabled'})

@odahcamコメントを関連するhttps

@Splaktarよし、投稿しました。

上記のSmaugsソリューションとstackoverflowのGuilhermeMeirelesを組み合わせると、うまくいきます。 また、リークを回避するためにngOnDestroyのサブスクライブを解除します。

import { Component } from '@angular/core'; 
import { Router, NavigationEnd } from '@angular/router'; 
import { Subscription } from 'rxjs/Rx';

@Component({
    moduleId: module.id, 
    selector: ‘my-app’,
    template: `<router-outlet></router-outlet>`
})

export class AppComponent {
    routerSubscription: Subscription;

    constructor(private router: Router) {}

    ngOnInit() {
        this.routerSubscription = this.router.events
            .filter(event => event instanceof NavigationEnd)
            .subscribe(event => {
                document.body.scrollTop = 0;
            });
    }

    ngOnDestroy() {
        this.routerSubscription.unsubscribe();
    }
}

Observableでfilter()、map()などの演算子を使用できない場合これを追加:

import { filter, map } from 'rxjs/operators';

Angular 6.1以降:

RouterModule.forRoot(routes、{scrollPositionRestoration: 'enabled'})

後方ナビゲーションでスクロール位置を維持し、前方ナビゲーションで上にスクロールするためのシンプルでクリーンなソリューションを探している他の人にとって、これはソリューションです。 将来的にはデフォルトのAngular動作になります(Angular仕様で説明されています:https://angular.io/api/router/ExtraOptions)

Angular 6.1以降:
RouterModule.forRoot(routes、{scrollPositionRestoration: 'enabled'})

後方ナビゲーションでスクロール位置を維持し、前方ナビゲーションで上にスクロールするためのシンプルでクリーンなソリューションを探している他の人にとって、これはソリューションです。 将来的にはデフォルトのAngular動作になります(Angular仕様で説明されています:https://angular.io/api/router/ExtraOptions)

親指を半分上げたい! 😅

次のExtraOptions

// ...
const routerOptions: ExtraOptions = {
  useHash: false,
  anchorScrolling: 'enabled',
  scrollPositionRestoration: 'enabled'
};
// ...

アンカーリンクを有効にするために、アンカーがページの下部にある場合でも、常に上部に表示されます。

ただし、アンカーナビゲーションを使用していない場合は、すばらしい修正です。 😉

この問題は、非アクティブのために自動的にロックされています。
同様の問題または関連する問題が発生した場合は、新しい問題を提出してください。

自動会話ロックポリシーの詳細をご覧ください。

_このアクションはボットによって自動的に実行されました。_

このページは役に立ちましたか?
0 / 5 - 0 評価