Angular 2 でルート変更時にページ上部へスクロールするベストプラクティス
Angular 2 でルート変更時にページ上部へスクロールする方法
router.events
オブザーバを利用して、ルート変更を検知し、スクロールを行う方法です。これは最も簡単な方法ですが、すべての状況でうまくいくとは限りません。
import { Router, NavigationStart } from '@angular/router';
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
constructor(private router: Router) {}
ngOnInit() {
this.router.events.subscribe((event) => {
if (event instanceof NavigationStart) {
window.scrollTo(0, 0);
}
});
}
}
この方法では、NavigationStart
イベントが発生した時に、window.scrollTo(0, 0)
を呼び出してページ上部へスクロールします。
@HostListener
デコレータを利用して、コンポーネントのルート変更イベントを検知し、スクロールを行う方法です。これは、router.events
を利用する方法よりも柔軟性がありますが、コード量が増えてしまいます。
import { Component, HostListener } from '@angular/core';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
@HostListener('window:hashchange')
onHashChange() {
window.scrollTo(0, 0);
}
}
NgZone
を利用して、Angular ゾーン内でスクロールを行う方法です。これは、@HostListener
を利用する方法よりも複雑ですが、より安全な方法です。
import { Component, NgZone } from '@angular/core';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
constructor(private zone: NgZone) {}
onRouteChange() {
this.zone.run(() => {
window.scrollTo(0, 0);
});
}
}
この方法では、onRouteChange
メソッド内で zone.run
を呼び出して、Angular ゾーン内でスクロールを行います。
ライブラリを利用する
ngx-scrolltop
などのライブラリを利用する方法もあります。ライブラリを利用すれば、コードを簡単に書くことができますが、ライブラリのバージョン管理や更新が必要になります。
import { Component } from '@angular/core';
import { ScrollTopService } from 'ngx-scrolltop';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
constructor(private scrollTopService: ScrollTopService) {}
onRouteChange() {
this.scrollTopService.scrollToTop();
}
}
この方法では、onRouteChange
メソッド内で scrollTopService.scrollToTop
メソッドを呼び出して、ページ上部へスクロールします。
Angular 2 でルート変更時にページ上部へスクロールするには、いくつかの方法があります。どの方法を使うかは、状況によって異なります。
- 簡単な方法で実装したい場合は、
router.events
を利用する方法がおすすめです。 - コードを簡単に書きたい場合は、ライブラリを利用する方法がおすすめです。
router.events を利用する
import { Router, NavigationStart } from '@angular/router';
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
constructor(private router: Router) {}
ngOnInit() {
this.router.events.subscribe((event) => {
if (event instanceof NavigationStart) {
window.scrollTo(0, 0);
}
});
}
}
@HostListener を利用する
import { Component, HostListener } from '@angular/core';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
@HostListener('window:hashchange')
onHashChange() {
window.scrollTo(0, 0);
}
}
NgZone を利用する
import { Component, NgZone } from '@angular/core';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
constructor(private zone: NgZone) {}
onRouteChange() {
this.zone.run(() => {
window.scrollTo(0, 0);
});
}
}
ライブラリを利用する
import { Component } from '@angular/core';
import { ScrollTopService } from 'ngx-scrolltop';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
constructor(private scrollTopService: ScrollTopService) {}
onRouteChange() {
this.scrollTopService.scrollToTop();
}
}
- 上記のサンプルコードは、基本的なものです。必要に応じて、コードを変更してください。
- Angular 2 のバージョンによって、コードの書き方が異なる場合があります。
Angular 2 でルート変更時にページ上部へスクロールするその他の方法
router.events
と BehaviorSubject
を利用して、現在のルート情報を保持し、ルート変更時にページ上部へスクロールする方法です。
import { Router, NavigationEnd, BehaviorSubject } from '@angular/router';
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
private currentRoute: BehaviorSubject<string> = new BehaviorSubject('');
constructor(private router: Router) {}
ngOnInit() {
this.router.events.subscribe((event) => {
if (event instanceof NavigationEnd) {
this.currentRoute.next(event.urlAfterRedirects);
}
});
this.currentRoute.subscribe((route) => {
if (route) {
window.scrollTo(0, 0);
}
});
}
}
この方法では、router.events
を利用して現在のルート情報を BehaviorSubject
に保持し、ルート変更時に window.scrollTo(0, 0)
を呼び出してページ上部へスクロールします。
CanActivate
ガードを利用して、ルート変更前にページ上部へスクロールする方法です。
import { Injectable } from '@angular/core';
import { CanActivate, Router } from '@angular/router';
@Injectable({
providedIn: 'root'
})
export class ScrollTopGuard implements CanActivate {
constructor(private router: Router) {}
canActivate(): boolean {
window.scrollTo(0, 0);
return true;
}
}
@ViewChild
を利用して、コンポーネント内の要素を取得し、スクロールを行う方法です。
import { Component, ViewChild } from '@angular/core';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
@ViewChild('appContent') appContent: ElementRef;
onRouteChange() {
this.appContent.nativeElement.scrollTo(0, 0);
}
}
この方法では、@ViewChild
を利用してコンポーネント内の appContent
要素を取得し、nativeElement.scrollTo(0, 0)
を呼び出してページ上部へスクロールします。
- ルート変更前にスクロールしたい場合は、
CanActivate
ガードを利用する方法がおすすめです。 - コンポーネント内の要素を取得してスクロールしたい場合は、
@ViewChild
を利用する方法がおすすめです。
angular typescript angular2-routing