Sudut 2 Gulir ke atas saat Perubahan Rute

296

Dalam aplikasi Angular 2 saya ketika saya menggulir ke bawah halaman dan mengklik tautan di bagian bawah halaman, itu memang mengubah rute dan membawa saya ke halaman berikutnya tetapi itu tidak gulir ke bagian atas halaman. Akibatnya, jika halaman pertama panjang dan halaman ke-2 memiliki sedikit konten, itu memberi kesan bahwa halaman ke-2 tidak memiliki konten. Karena konten hanya dapat dilihat jika pengguna menggulir ke bagian atas halaman.

Saya dapat menggulirkan jendela ke bagian atas halaman dengan ngInit dari komponen tetapi, apakah ada solusi yang lebih baik yang secara otomatis dapat menangani semua rute di aplikasi saya?

Naveed Ahmed
sumber
20
Sejak Angular 6.1 kita dapat menggunakan {scrollPositionRestoration: 'enabled'} pada modul yang penuh semangat atau hanya di app.module dan akan diterapkan ke semua rute. RouterModule.forRoot(appRoutes, { scrollPositionRestoration: 'enabled' })
Manwal
Muito obrigado sua solução funcionou perfeitamente para mim :)
Raphael Godoi
tidak satu orang disebutkan fokus? ini lebih penting daripada sebelumnya untuk mendukung aksesibilitas / pembaca layar dengan benar dan jika Anda cukup gulir ke atas tanpa mempertimbangkan fokus maka penekanan tombol tab berikutnya dapat melompat ke bagian bawah layar.
Simon_Weaver

Jawaban:

386

Anda dapat mendaftarkan pendengar perubahan rute pada komponen utama Anda dan gulir ke atas pada perubahan rute.

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)
        });
    }
}
Guilherme Meireles
sumber
11
window.scrollTo(0, 0)adalah document.body.scrollTop = 0;IMO yang lebih ringkas daripada , dan lebih mudah dibaca.
Mark E. Haase
10
Adakah yang memperhatikan, bahwa bahkan setelah menerapkan ini, masalah tetap ada di browser safari Iphone. ada pemikiran?
rgk
1
@mease Sepertinya jawaban Anda adalah yang terbaik. window.body.scrollTop tidak berfungsi untuk saya di desktop Firefox. Jadi terima kasih
KCarnaille
3
Ini bekerja untuk saya, tetapi itu merusak perilaku tombol "kembali" default. Kembali harus mengingat posisi gulir sebelumnya.
JackKalish
6
Ini berhasil !! Meskipun saya menambahkan $("body").animate({ scrollTop: 0 }, 1000);daripada window.scrollTo(0, 0)menghidupkan
gulungan
360

Sudut 6.1 dan yang lebih baru :

Angular 6.1 (dirilis pada 2018-07-25) menambahkan dukungan bawaan untuk menangani masalah ini, melalui fitur yang disebut "Router Scroll Position Restoration". Seperti yang dijelaskan di blog resmi Angular , Anda hanya perlu mengaktifkan ini di konfigurasi router seperti ini:

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

Selanjutnya, blog menyatakan "Diharapkan bahwa ini akan menjadi default dalam rilis utama di masa depan". Sejauh ini ini belum terjadi (pada Angular 8.2), tetapi pada akhirnya Anda tidak perlu melakukan apa pun dalam kode Anda, dan ini hanya akan berfungsi dengan baik di luar kotak.

Anda dapat melihat detail lebih lanjut tentang fitur ini dan cara menyesuaikan perilaku ini di dokumen resmi .

6.0 sudut dan sebelumnya :

Sementara jawaban GuilhermeMeireles yang luar biasa memperbaiki masalah aslinya, ia memperkenalkan yang baru, dengan memutus perilaku normal yang Anda harapkan ketika Anda menavigasi kembali atau meneruskan (dengan tombol browser atau melalui Lokasi dalam kode). Perilaku yang diharapkan adalah ketika Anda menavigasi kembali ke halaman, itu harus tetap digulir ke bawah ke lokasi yang sama ketika Anda mengklik tautan, tetapi menggulir ke atas ketika tiba di setiap halaman jelas-jelas mematahkan harapan ini.

Kode di bawah ini memperluas logika untuk mendeteksi navigasi semacam ini dengan berlangganan urutan PopStateEvent Lokasi dan melewatkan logika scroll-to-top jika halaman yang baru tiba adalah hasil dari peristiwa semacam itu.

Jika halaman yang Anda navigasikan kembali cukup panjang untuk menutupi seluruh viewport, posisi gulir dipulihkan secara otomatis, tetapi seperti yang ditunjukkan oleh @JordanNelson, jika halaman lebih pendek, Anda perlu melacak posisi gulir y asli dan mengembalikannya secara eksplisit ketika Anda kembali ke halaman. Versi kode yang diperbarui mencakup kasus ini juga, dengan selalu secara eksplisit mengembalikan posisi gulir.

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);
            }
        });
    }
}
Fernando Echeverria
sumber
2
Ini harus masuk dalam komponen aplikasi secara langsung, atau dalam satu komponen yang digunakan di dalamnya (dan karenanya dibagikan oleh seluruh aplikasi). Misalnya, saya telah memasukkannya dalam komponen bilah navigasi atas. Anda seharusnya tidak termasuk dalam semua komponen Anda.
Fernando Echeverria
3
Anda dapat melakukannya dan itu akan membuat kode lebih kompatibel dengan platform non-browser lainnya. Lihat stackoverflow.com/q/34177221/2858481 untuk detail implementasi.
Fernando Echeverria
3
Jika Anda mengklik dan menahan tombol kembali / maju di browser modern, akan muncul menu yang memungkinkan Anda menavigasi ke lokasi selain yang sebelumnya / berikutnya. Solusi ini rusak jika Anda melakukannya. Ini kasus tepi bagi sebagian besar, tetapi layak disebutkan.
adamdport
1
Apakah ada cara untuk mengaktifkan "Restorasi Posisi Gulir Router" untuk elemen bersarang atau hanya berfungsi untuk body?
vulp
61

Dari Angular 6.1, Anda sekarang dapat menghindari kerumitan dan beralih extraOptionske RouterModule.forRoot()parameter Anda sebagai parameter kedua dan dapat menentukan scrollPositionRestoration: enableduntuk memberitahu Angular untuk menggulir ke atas setiap kali rute berubah.

Secara default Anda akan menemukan ini di app-routing.module.ts:

const routes: Routes = [
  {
    path: '...'
    component: ...
  },
  ...
];

@NgModule({
  imports: [
    RouterModule.forRoot(routes, {
      scrollPositionRestoration: 'enabled', // Add options right here
    })
  ],
  exports: [RouterModule]
})
export class AppRoutingModule { }

Dokumen Resmi Sudut

Abdul Rafay
sumber
3
Meskipun jawaban di atas lebih deskriptif, saya suka bahwa jawaban ini memberi tahu saya dengan tepat ke mana harus pergi
ryanovas
32

Anda dapat menulis ini dengan lebih ringkas dengan memanfaatkan filtermetode yang bisa diamati :

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

Jika Anda mengalami masalah untuk menggulir ke atas saat menggunakan sidenav Bahan Sudut 2 ini akan membantu. Jendela atau badan dokumen tidak akan memiliki bilah gulir sehingga Anda perlu mendapatkan sidenavwadah konten dan gulir elemen itu, jika tidak coba gulir jendela sebagai default.

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

Juga, Angular CDK v6.x sekarang memiliki paket gulir yang mungkin membantu menangani pengguliran.

mtpultz
sumber
2
Bagus! Bagi saya itu berhasil -document.querySelector('.mat-sidenav-content .content-div').scrollTop = 0;
Amir Tugi
Bagus satu kawan ... di mtpultz & @AmirTugi. Berurusan dengan ini sekarang, dan Anda berhasil melakukannya untuk saya, tepuk tangan! Mungkin akhirnya akan menggulung sisi saya sendiri karena Bahan 2 tidak bermain bagus ketika md-toolbar adalah posisi: diperbaiki (di atas). Kecuali kalian punya ide .... ????
Tim Harker
Mungkin sudah menemukan jawaban saya ... stackoverflow.com/a/40396105/3389046
Tim Harker
16

Jika Anda memiliki rendering sisi server, Anda harus berhati-hati untuk tidak menjalankan kode yang digunakan windowspada server, di mana variabel itu tidak ada. Ini akan menghasilkan pemecahan kode.

export class AppComponent implements OnInit {
  routerSubscription: Subscription;

  constructor(private router: Router,
              @Inject(PLATFORM_ID) private platformId: any) {}

  ngOnInit() {
    if (isPlatformBrowser(this.platformId)) {
      this.routerSubscription = this.router.events
        .filter(event => event instanceof NavigationEnd)
        .subscribe(event => {
          window.scrollTo(0, 0);
        });
    }
  }

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

isPlatformBrowseradalah fungsi yang digunakan untuk memeriksa apakah platform saat ini di mana aplikasi diberikan adalah browser atau tidak. Kami berikan yang disuntikkan platformId.

Itu juga mungkin untuk memeriksa keberadaan variabel windows, agar aman, seperti ini:

if (typeof window != 'undefined')
Raptor
sumber
1
Apakah Anda tidak perlu menyuntikkan PLATFORM_IDdalam constructordan memberikan nilai ini sebagai parameter dalam de isPlatformBrowsermetode?
Poul Kruijt
1
@PierreDuc Ya, jawabannya salah. isPlatformBrowseradalah fungsi dan akan selalu jujur. Saya sudah mengeditnya sekarang.
Lazar Ljubenović
Terima kasih! Benar sekarang! Baru saja memverifikasi API: github.com/angular/angular/blob/…
Raptor
13

lakukan saja dengan mudah dengan aksi klik

di html komponen utama Anda buat referensi #scrollContainer

<div class="main-container" #scrollContainer>
    <router-outlet (activate)="onActivate($event, scrollContainer)"></router-outlet>
</div>

di komponen utama .ts

onActivate(e, scrollContainer) {
    scrollContainer.scrollTop = 0;
}
DUDUK
sumber
Elemen yang akan digulir mungkin tidak ada di scrollContainernode pertama, Anda mungkin perlu menggali sedikit di objek, bagi saya apa yang benar-benar berfungsi adalahscrollContainer .scrollable._elementRef.nativeElement.scrollTop = 0
Byron Lopez
13

Angular baru-baru ini memperkenalkan fitur baru, di dalam modul routing sudut melakukan perubahan seperti di bawah ini

@NgModule({
  imports: [RouterModule.forRoot(routes,{
    scrollPositionRestoration: 'top'
  })],
RV Pran
sumber
12

Jawaban terbaik ada di diskusi Angular GitHub ( Mengubah rute tidak gulir ke atas di halaman baru ).

Mungkin Anda ingin pergi ke atas hanya dalam perubahan router root (bukan pada anak-anak, karena Anda dapat memuat rute dengan lazy load di a tabset)

app.component.html

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

app.component.ts

onDeactivate() {
  document.body.scrollTop = 0;
  // Alternatively, you can scroll to top by using this other call:
  // window.scrollTo(0, 0)
}

Kredit penuh untuk JoniJnm ( pos asli )

zurfyx
sumber
8

Anda dapat menambahkan kait siklus hidup AfterViewInit ke komponen Anda.

ngAfterViewInit() {
   window.scrollTo(0, 0);
}
stillatmylinux
sumber
7

Pada Angular 6.1, router menyediakan opsi konfigurasi yang disebut scrollPositionRestoration, ini dirancang untuk memenuhi skenario ini.

imports: [
  RouterModule.forRoot(routes, {
    scrollPositionRestoration: 'enabled'
  }),
  ...
]
Marty A
sumber
4

Jika Anda hanya perlu menggulir halaman ke atas, Anda dapat melakukan ini (bukan solusi terbaik, tetapi cepat)

document.getElementById('elementId').scrollTop = 0;
Aliaksei
sumber
4

Inilah solusi yang saya buat. Saya memasangkan LocationStrategy dengan peristiwa Router. Menggunakan LocationStrategy untuk menetapkan boolean untuk mengetahui kapan pengguna saat ini menelusuri riwayat peramban. Dengan cara ini, saya tidak perlu menyimpan banyak URL dan data gulir y (yang tidak berfungsi dengan baik, karena setiap data diganti berdasarkan URL). Ini juga menyelesaikan tepi kasus ketika pengguna memutuskan untuk menahan tombol maju atau mundur pada browser dan kembali atau maju beberapa halaman daripada hanya satu.

PS Saya hanya menguji pada versi terbaru dari IE, Chrome, FireFox, Safari, dan Opera (pada posting ini).

Semoga ini membantu.

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_808
sumber
4

Solusi ini didasarkan pada solusi @ FernandoEcheverria dan @ GuilhermeMeireles, tetapi lebih ringkas dan berfungsi dengan mekanisme popstate yang disediakan oleh Angular Router. Ini memungkinkan untuk menyimpan dan mengembalikan level gulir dari beberapa navigasi berurutan.

Kami menyimpan posisi gulir untuk setiap kondisi navigasi di peta scrollLevels. Setelah ada acara popstate, ID dari negara yang akan dikembalikan dipasok oleh sudut Router: event.restoredState.navigationId. Ini kemudian digunakan untuk mendapatkan tingkat gulir terakhir dari kondisi ituscrollLevels .

Jika tidak ada level gulir yang tersimpan untuk rute, itu akan bergulir ke atas seperti yang Anda harapkan.

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

@Component({
    selector: 'my-app',
    template: '<ng-content></ng-content>',
})
export class AppComponent implements OnInit {

  constructor(private router: Router) { }

  ngOnInit() {
    const scrollLevels: { [navigationId: number]: number } = {};
    let lastId = 0;
    let restoredId: number;

    this.router.events.subscribe((event: Event) => {

      if (event instanceof NavigationStart) {
        scrollLevels[lastId] = window.scrollY;
        lastId = event.id;
        restoredId = event.restoredState ? event.restoredState.navigationId : undefined;
      }

      if (event instanceof NavigationEnd) {
        if (restoredId) {
          // Optional: Wrap a timeout around the next line to wait for
          // the component to finish loading
          window.scrollTo(0, scrollLevels[restoredId] || 0);
        } else {
          window.scrollTo(0, 0);
        }
      }

    });
  }

}
Simon Mathewson
sumber
Luar biasa. Saya harus membuat versi yang sedikit khusus untuk menggulir div daripada jendela, tetapi itu berhasil. Salah satu perbedaan utama adalah scrollTopvs scrollY.
BBaysinger
4

Selain jawaban sempurna yang diberikan oleh @Guilherme Meireles seperti yang ditunjukkan di bawah ini, Anda dapat mengubah penerapan Anda dengan menambahkan gulir halus seperti yang ditunjukkan di bawah ini

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

lalu tambahkan cuplikan di bawah ini

 html {
      scroll-behavior: smooth;
    }

ke styles.css Anda

Ifesinachi Bryan
sumber
1

untuk iphone / ios safari Anda dapat membungkusnya dengan setTimeout

setTimeout(function(){
    window.scrollTo(0, 1);
}, 0);
tubbsy
sumber
dalam kasus saya itu juga mengharuskan elemen pembungkus halaman css diatur ke; height: 100vh + 1px;
tubbsy
1

Hai guys ini bekerja untuk saya di sudut 4. Anda hanya perlu referensi orang tua untuk gulir pada perubahan router`

layout.component.pug

.wrapper(#outlet="")
    router-outlet((activate)='routerActivate($event,outlet)')

layout.component.ts

 public routerActivate(event,outlet){
    outlet.scrollTop = 0;
 }`
Jonas Arguelles
sumber
1
maafkan kemalasan saya karena tidak repot-repot belajar pesek, tapi bisakah Anda menerjemahkan ke HTML?
CodyBugstein
0

@Fernando Echeverria hebat! tetapi kode ini tidak berfungsi di router hash atau router malas. karena mereka tidak memicu perubahan lokasi. dapat mencoba ini:

private lastRouteUrl: string[] = []
  

ngOnInit(): void {
  this.router.events.subscribe((ev) => {
    const len = this.lastRouteUrl.length
    if (ev instanceof NavigationEnd) {
      this.lastRouteUrl.push(ev.url)
      if (len > 1 && ev.url === this.lastRouteUrl[len - 2]) {
        return
      }
      window.scrollTo(0, 0)
    }
  })
}

Witt Bulter
sumber
0

Menggunakannya Routersendiri akan menyebabkan masalah yang tidak dapat Anda atasi sepenuhnya untuk mempertahankan pengalaman browser yang konsisten. Menurut pendapat saya metode terbaik adalah dengan hanya menggunakan kebiasaan directivedan biarkan ini mereset gulir saat klik. Hal yang baik tentang ini, adalah bahwa jika Anda berada di sama urldengan yang Anda klik, halaman akan menggulir kembali ke atas juga. Ini konsisten dengan situs web normal. Dasardirective bisa terlihat seperti ini:

import {Directive, HostListener} from '@angular/core';

@Directive({
    selector: '[linkToTop]'
})
export class LinkToTopDirective {

    @HostListener('click')
    onClick(): void {
        window.scrollTo(0, 0);
    }
}

Dengan penggunaan berikut:

<a routerLink="/" linkToTop></a>

Ini akan cukup untuk sebagian besar kasus penggunaan, tapi saya bisa membayangkan beberapa masalah yang mungkin timbul dari ini:

  • Tidak berfungsi universal karena penggunaanwindow
  • Kecepatan kecil berdampak pada deteksi perubahan, karena dipicu oleh setiap klik
  • Tidak ada cara untuk menonaktifkan arahan ini

Sebenarnya cukup mudah untuk mengatasi masalah ini:

@Directive({
  selector: '[linkToTop]'
})
export class LinkToTopDirective implements OnInit, OnDestroy {

  @Input()
  set linkToTop(active: string | boolean) {
    this.active = typeof active === 'string' ? active.length === 0 : active;
  }

  private active: boolean = true;

  private onClick: EventListener = (event: MouseEvent) => {
    if (this.active) {
      window.scrollTo(0, 0);
    }
  };

  constructor(@Inject(PLATFORM_ID) private readonly platformId: Object,
              private readonly elementRef: ElementRef,
              private readonly ngZone: NgZone
  ) {}

  ngOnDestroy(): void {
    if (isPlatformBrowser(this.platformId)) {
      this.elementRef.nativeElement.removeEventListener('click', this.onClick, false);
    }
  }

  ngOnInit(): void {
    if (isPlatformBrowser(this.platformId)) {
      this.ngZone.runOutsideAngular(() => 
        this.elementRef.nativeElement.addEventListener('click', this.onClick, false)
      );
    }
  }
}

Ini memperhitungkan sebagian besar kasus penggunaan, dengan penggunaan yang sama seperti kasus dasar, dengan keuntungan mengaktifkan / menonaktifkannya:

<a routerLink="/" linkToTop></a> <!-- always active -->
<a routerLink="/" [linkToTop]="isActive"> <!-- active when `isActive` is true -->

iklan, jangan baca jika Anda tidak ingin diiklankan

Perbaikan lain dapat dilakukan untuk memeriksa apakah browser mendukung passiveacara atau tidak . Ini akan memperumit kode sedikit lebih, dan agak tidak jelas jika Anda ingin menerapkan semua ini dalam arahan / templat kustom Anda. Itu sebabnya saya menulis perpustakaan kecil yang dapat Anda gunakan untuk mengatasi masalah ini. Untuk memiliki fungsi yang sama seperti di atas, dan dengan passiveacara yang ditambahkan , Anda dapat mengubah arahan Anda untuk ini, jika Anda menggunakan ng-event-optionsperpustakaan. Logikanya ada di dalam click.pnbpendengar:

@Directive({
    selector: '[linkToTop]'
})
export class LinkToTopDirective {

    @Input()
    set linkToTop(active: string|boolean) {
        this.active = typeof active === 'string' ? active.length === 0 : active;
    }

    private active: boolean = true;

    @HostListener('click.pnb')
    onClick(): void {
      if (this.active) {
        window.scrollTo(0, 0);
      }        
    }
}
Poul Kruijt
sumber
0

Ini bekerja untuk saya yang terbaik untuk semua perubahan navigasi termasuk navigasi hash

constructor(private route: ActivatedRoute) {}

ngOnInit() {
  this._sub = this.route.fragment.subscribe((hash: string) => {
    if (hash) {
      const cmp = document.getElementById(hash);
      if (cmp) {
        cmp.scrollIntoView();
      }
    } else {
      window.scrollTo(0, 0);
    }
  });
}
Jorg Janke
sumber
0

Gagasan utama di balik kode ini adalah untuk menjaga semua url yang dikunjungi bersama dengan data gulir masing-masing dalam array. Setiap kali pengguna meninggalkan halaman (NavigationStart) array ini diperbarui. Setiap kali pengguna memasuki halaman baru (NavigationEnd), kami memutuskan untuk mengembalikan posisi Y atau tidak tergantung pada bagaimana kita sampai ke halaman ini. Jika referensi pada beberapa halaman digunakan kita gulir ke 0. Jika fitur back / forward browser digunakan kita gulir ke Y disimpan dalam array kita. Maaf untuk bahasa Inggris saya :)

import { Component, OnInit, OnDestroy } from '@angular/core';
import { Location, PopStateEvent } from '@angular/common';
import { Router, Route, RouterLink, NavigationStart, NavigationEnd, 
    RouterEvent } from '@angular/router';
import { Subscription } from 'rxjs/Subscription';

@Component({
  selector: 'my-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit, OnDestroy {

  private _subscription: Subscription;
  private _scrollHistory: { url: string, y: number }[] = [];
  private _useHistory = false;

  constructor(
    private _router: Router,
    private _location: Location) {
  }

  public ngOnInit() {

    this._subscription = this._router.events.subscribe((event: any) => 
    {
      if (event instanceof NavigationStart) {
        const currentUrl = (this._location.path() !== '') 
           this._location.path() : '/';
        const item = this._scrollHistory.find(x => x.url === currentUrl);
        if (item) {
          item.y = window.scrollY;
        } else {
          this._scrollHistory.push({ url: currentUrl, y: window.scrollY });
        }
        return;
      }
      if (event instanceof NavigationEnd) {
        if (this._useHistory) {
          this._useHistory = false;
          window.scrollTo(0, this._scrollHistory.find(x => x.url === 
          event.url).y);
        } else {
          window.scrollTo(0, 0);
        }
      }
    });

    this._subscription.add(this._location.subscribe((event: PopStateEvent) 
      => { this._useHistory = true;
    }));
  }

  public ngOnDestroy(): void {
    this._subscription.unsubscribe();
  }
}
Vladimir Turygin
sumber
0

window.scrollTo()tidak bekerja untuk saya dalam Angular 5, jadi saya telah menggunakan document.body.scrollTopseperti,

this.router.events.subscribe((evt) => {
   if (evt instanceof NavigationEnd) {
      document.body.scrollTop = 0;
   }
});
Rohan Kumar
sumber
0

Jika Anda memuat komponen yang berbeda dengan rute yang sama maka Anda dapat menggunakan ViewportScroller untuk mencapai hal yang sama.

import { ViewportScroller } from '@angular/common';

constructor(private viewportScroller: ViewportScroller) {}

this.viewportScroller.scrollToPosition([0, 0]);
berpasir
sumber
0

window scroll top
Kedua window.pageYOffset dan document.documentElement.scrollTop mengembalikan hasil yang sama di semua case. window.pageYOffset tidak didukung di bawah IE 9.

app.component.ts

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

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  isShow: boolean;
  topPosToStartShowing = 100;

  @HostListener('window:scroll')
  checkScroll() {

    const scrollPosition = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;

    console.log('[scroll]', scrollPosition);

    if (scrollPosition >= this.topPosToStartShowing) {
      this.isShow = true;
    } else {
      this.isShow = false;
    }
  }

  gotoTop() {
    window.scroll({ 
      top: 0, 
      left: 10, 
      behavior: 'smooth' 
    });
  }
}

app.component.html

<style>
  p {
  font-family: Lato;
}

button {
  position: fixed;
  bottom: 5px;
  right: 5px;
  font-size: 20px;
  text-align: center;
  border-radius: 5px;
  outline: none;
}
  </style>
<p>
  Lorem ipsum dolor sit, amet consectetur adipisicing elit. Minus, repudiandae quia. Veniam amet fuga, eveniet velit ipsa repudiandae nemo? Sit dolorem itaque laudantium dignissimos, rerum maiores nihil ad voluptates nostrum.
</p>
<p>
  Lorem ipsum dolor sit, amet consectetur adipisicing elit. Minus, repudiandae quia. Veniam amet fuga, eveniet velit ipsa repudiandae nemo? Sit dolorem itaque laudantium dignissimos, rerum maiores nihil ad voluptates nostrum.
</p>
<p>
  Lorem ipsum dolor sit, amet consectetur adipisicing elit. Minus, repudiandae quia. Veniam amet fuga, eveniet velit ipsa repudiandae nemo? Sit dolorem itaque laudantium dignissimos, rerum maiores nihil ad voluptates nostrum.
</p>
<p>
  Lorem ipsum dolor sit, amet consectetur adipisicing elit. Minus, repudiandae quia. Veniam amet fuga, eveniet velit ipsa repudiandae nemo? Sit dolorem itaque laudantium dignissimos, rerum maiores nihil ad voluptates nostrum.
</p>
<p>
  Lorem ipsum dolor sit, amet consectetur adipisicing elit. Minus, repudiandae quia. Veniam amet fuga, eveniet velit ipsa repudiandae nemo? Sit dolorem itaque laudantium dignissimos, rerum maiores nihil ad voluptates nostrum.
</p>
<p>
  Lorem ipsum dolor sit, amet consectetur adipisicing elit. Minus, repudiandae quia. Veniam amet fuga, eveniet velit ipsa repudiandae nemo? Sit dolorem itaque laudantium dignissimos, rerum maiores nihil ad voluptates nostrum.
</p>
<p>
  Lorem ipsum dolor sit, amet consectetur adipisicing elit. Minus, repudiandae quia. Veniam amet fuga, eveniet velit ipsa repudiandae nemo? Sit dolorem itaque laudantium dignissimos, rerum maiores nihil ad voluptates nostrum.
</p>
<p>
  Lorem ipsum dolor sit, amet consectetur adipisicing elit. Minus, repudiandae quia. Veniam amet fuga, eveniet velit ipsa repudiandae nemo? Sit dolorem itaque laudantium dignissimos, rerum maiores nihil ad voluptates nostrum.
</p>

<button *ngIf="isShow" (click)="gotoTop()">👆</button>
yogesh waghmare
sumber