Açısal 5 Her Rota tıklamasında en üste kaydırın


117

Açısal 5 kullanıyorum. Küçük içeriğe sahip birkaç bölümüm ve çok büyük içeriğe sahip birkaç bölümün olduğu bir kontrol panelim var ki, yukarı çıkarken yönlendiriciyi değiştirirken bir sorunla karşılaşıyorum. Yukarı gitmek için her zaman kaydırmam gerekiyor. Herhangi biri bu sorunu çözmeme yardım edebilir mi, böylece yönlendiriciyi değiştirdiğimde görüşüm her zaman en üstte kalır.

Şimdiden teşekkürler.


Olası Angular 2
Cerbrus

Yanıtlar:


240

Bazı çözümler var, hepsini kontrol ettiğinizden emin olun :)


Yönlendirici çıkışı, activateyeni bir bileşen başlatılırken olayı yayınlayacaktır , böylece (activate)(örneğin) en üste kaydırmak için kullanabiliriz :

app.component.html

<router-outlet (activate)="onActivate($event)" ></router-outlet>

app.component.ts

onActivate(event) {
    window.scroll(0,0);
    //or document.body.scrollTop = 0;
    //or document.querySelector('body').scrollTo(0,0)
    ...
}

Örneğin, pürüzsüz bir kaydırma için bu çözümü kullanın :

    onActivate(event) {
        let scrollToTop = window.setInterval(() => {
            let pos = window.pageYOffset;
            if (pos > 0) {
                window.scrollTo(0, pos - 20); // how far to scroll on each step
            } else {
                window.clearInterval(scrollToTop);
            }
        }, 16);
    }

Seçici olmak istiyorsanız, her bileşenin kaydırmayı tetiklememesi gerektiğini söyleyin, aşağıdaki ifgibi bir ifadeyle kontrol edebilirsiniz :

onActivate(e) {
    if (e.constructor.name)==="login"{ // for example
            window.scroll(0,0);
    }
}

Angular6.1'den beri { scrollPositionRestoration: 'enabled' }, merakla yüklenen modüller üzerinde de kullanabiliriz ve tüm rotalara uygulanacaktır:

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

Zaten düzgün kaydırmayı da yapacak. Ancak bu, her yönlendirmede bunu yapmak için sakıncalıdır.


Diğer bir çözüm, yönlendirici animasyonunda en üst kaydırmayı yapmaktır. Bunu, en üste kaydırmak istediğiniz her geçişe ekleyin:

query(':enter, :leave', style({ position: 'fixed' }), { optional: true }) 

4
işe yarıyor . Cevabınız için teşekkürler. benim için çok zaman
kazanıyorsun

2
windownesne üzerindeki kaydırma olayları açısal olarak çalışmıyor 5. Herhangi bir tahmin neden?
Sahil Babbar

2
Burada gerçek bir kahraman. Olası hayal kırıklığı saatlerinden kurtardı. Teşekkür ederim!
Anjana Silva

1
@AnjanaSilva, olumlu yorumunuz için teşekkürler! Size yardımcı olabileceğine çok sevindim :)
Vega

2
Lazyloaded modülün herhangi bir yolu var mı?
Pankaj Prakash

57

Angular 6'da bu sorunla karşılaşırsanız, parametreyi scrollPositionRestoration: 'enabled'app-routing.module.ts'nin RouterModule'ına ekleyerek düzeltebilirsiniz:

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

5
6 Kasım 2019 tarihinden itibaren Angular 8 kullanıldığında, en azından scrollPositionRestorationözelliğin dinamik sayfa içeriğiyle (yani sayfa içeriğinin eşzamansız olarak yüklendiği yerlerde) çalışmadığını unutmayın
dbeachy1

27

DÜZENLEME: Angular 6+ için lütfen Nimesh Nishara Indimagedara'nın şu cevabını kullanın:

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

Orijinal Cevap:

Tümü başarısız olursa, üstte (veya istenen konuma kaydırarak) şablonda (veya ana şablonda) id = "top" ile boş bir HTML öğesi oluşturun (ör. Div):

<div id="top"></div>

Ve bileşen olarak:

  ngAfterViewInit() {
    // Hack: Scrolls to top of Page after page view initialized
    let top = document.getElementById('top');
    if (top !== null) {
      top.scrollIntoView();
      top = null;
    }
  }

2
Bu çözüm benim için çalıştı (Chrome ve Edge'de test edildi). Kabul edilen çözüm projem için işe yaramadı (Angular5)
Rob van Meeuwen

@RobvanMeeuwen, Cevabım işe yaramadıysa, muhtemelen aynı şekilde uygulamadınız. Bu çözüm, güvenli olmayan DOM'u doğrudan manipüle ediyor
Vega

@Vega, bu yüzden ona hack dedim. Sizin çözümünüz doğru olanıdır. Buradaki bazı kişiler sizinkini uygulayamadı, bu yüzden yedek hack'i önerdim. Kodlarını bu noktada bulundukları sürüme göre yeniden düzenlemelidirler.
GeoRover

Tüm bu çözümden benim için iş. Teşekkürler @GeoRover
Gangani Roshan

Angular 6+ için lütfen Nimesh Nishara Indimagedara'nın cevabını kullanın.
GeoRover


7

@Vega sorunuza doğrudan yanıt verse de bazı sorunlar var. Tarayıcının geri / ileri düğmesini kırar. Kullanıcı, tarayıcı geri veya ileri düğmesini tıklarsa, yerlerini kaybederler ve en üstte kaydırılırlar. Bu, kullanıcılarınız için bir bağlantıya ulaşmak için aşağı kaydırmak zorunda kalırsa ve yalnızca kaydırma çubuğunun en üste sıfırlandığını bulmak için geri tıklamaya karar verirse biraz acı verebilir.

İşte soruna çözümüm.

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

2
Gelişmiş kod ve güzel çözüm için teşekkür ederiz. Ancak bazen @Vega çözümü daha iyidir, çünkü animasyon ve dinamik sayfa yüksekliği ile birçok sorunu çözer. İçeriğe ve basit yönlendirme animasyonuna sahip uzun bir sayfanız varsa çözümünüz iyidir. Birçok animasyon ve dinamik bloğu olan sayfada deniyorum ve pek iyi görünmüyor. Bazen uygulamamız için 'geri konumdan' ödün verebileceğimizi düşünüyorum. Ama değilse - çözümünüz, Angular için gördüğüm en iyisidir. Tekrar teşekkür ederim
Denis Savenko

6

Angular Versiyon 6+ 'dan window.scroll (0,0) kullanmaya gerek yok

Açısal sürüm 6+için @ yönlendiriciyi yapılandırma seçeneklerini temsil eder.docs

interface ExtraOptions {
  enableTracing?: boolean
  useHash?: boolean
  initialNavigation?: InitialNavigation
  errorHandler?: ErrorHandler
  preloadingStrategy?: any
  onSameUrlNavigation?: 'reload' | 'ignore'
  scrollPositionRestoration?: 'disabled' | 'enabled' | 'top'
  anchorScrolling?: 'disabled' | 'enabled'
  scrollOffset?: [number, number] | (() => [number, number])
  paramsInheritanceStrategy?: 'emptyOnly' | 'always'
  malformedUriErrorHandler?: (error: URIError, urlSerializer: UrlSerializer, url: string) => UrlTree
  urlUpdateStrategy?: 'deferred' | 'eager'
  relativeLinkResolution?: 'legacy' | 'corrected'
}

Bir kullanabilir scrollPositionRestoration?: 'disabled' | 'enabled' | 'top'içinde

Misal:

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

Ve kaydırmanın manuel olarak kontrol edilmesi gerekiyorsa, window.scroll(0,0) Angular V6 yerine kullanmaya gerek yok ortak paketi tanıtıldı ViewPortScoller.

abstract class ViewportScroller {
  static ngInjectableDef: defineInjectable({ providedIn: 'root', factory: () => new BrowserViewportScroller(inject(DOCUMENT), window) })
  abstract setOffset(offset: [number, number] | (() => [number, number])): void
  abstract getScrollPosition(): [number, number]
  abstract scrollToPosition(position: [number, number]): void
  abstract scrollToAnchor(anchor: string): void
  abstract setHistoryScrollRestoration(scrollRestoration: 'auto' | 'manual'): void
}

Kullanımı oldukça basittir Örnek:

import { Router } from '@angular/router';
import {  ViewportScroller } from '@angular/common'; //import
export class RouteService {

  private applicationInitialRoutes: Routes;
  constructor(
    private router: Router;
    private viewPortScroller: ViewportScroller//inject
  )
  {
   this.router.events.pipe(
            filter(event => event instanceof NavigationEnd))
            .subscribe(() => this.viewPortScroller.scrollToPosition([0, 0]));
}

5

Benim durumumda yeni ekledim

window.scroll(0,0);

içinde ngOnInit()ve iyi çalışıyor.


4

Açısal 6.1 ve sonrası:

Sen kullanabilirsiniz çözeltide inşa mevcut 6.1 ve sonraki açısal seçeneğiyle scrollPositionRestoration: 'enabled'aynı elde etmek.

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

Angular 6.0 ve öncesi:

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

Not: Beklenen davranış, sayfaya geri döndüğünüzde, bağlantıya tıkladığınızdaki aynı konuma aşağı kaydırılmış halde kalması, ancak her sayfaya ulaştığınızda en üste kaydırılmasıdır.


4

mat-sidenav kullanıyorsanız, yönlendirici çıkışına bir kimlik verirse (ebeveyn ve alt yönlendirici çıkışlarınız varsa) ve içindeki etkinleştirme işlevini <router-outlet id="main-content" (activate)="onActivate($event)"> kullanın ve yukarı kaydırmak için bu 'mat-sidenav-içerik' sorgu seçicisini kullanın onActivate(event) { document.querySelector("mat-sidenav-content").scrollTo(0, 0); }


Kullanmadan bile harika çalışıyor id ( router-outletuygulamamda bir single var). Bunu daha 'açısal' bir şekilde de yaptım: @ViewChild(MatSidenavContainer) sidenavContainer: MatSidenavContainer; onActivate() { this.sidenavContainer.scrollable.scrollTo({ left: 0, top: 0 }); }
GCSDC

3

AngularJS'de olduğu gibi bu soruna yerleşik bir çözüm aramaya devam ediyorum. Ancak o zamana kadar bu çözüm benim için çalışıyor, Çok basit ve geri düğmesi işlevselliğini koruyor.

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

Zurfyx original post tarafından gönderilen yanıt


3

Sadece ekranınızın kaydırma ayarını içeren bir işlev oluşturmanız gerekir.

Örneğin

window.scroll(0,0) OR window.scrollTo() by passing appropriate parameter.

window.scrollTo (xpos, ypos) -> beklenen parametre.



3

Kaydırma işlevi arayan biri için, yalnızca işlevi ekleyin ve gerektiğinde arayın

scrollbarTop(){

  window.scroll(0,0);
}

2

EACH bileşenini ilk kez ziyaret ettiğinizde yalnızca Bileşenin en üstüne kaydıran bir çözüm (bileşen başına farklı bir şey yapmanız gerektiğinde):

Her Bileşende:

export class MyComponent implements OnInit {

firstLoad: boolean = true;

...

ngOnInit() {

  if(this.firstLoad) {
    window.scroll(0,0);
    this.firstLoad = false;
  }
  ...
}

2

export class AppComponent {
  constructor(private router: Router) {
    router.events.subscribe((val) => {
      if (val instanceof NavigationEnd) {
        window.scrollTo(0, 0);
      }
    });
  }

}


1

Bunu dene:

app.component.ts

import {Component, OnInit, OnDestroy} from '@angular/core';
import {Router, NavigationEnd} from '@angular/router';
import {filter} from 'rxjs/operators';
import {Subscription} from 'rxjs';

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

    constructor(private router: Router) {
    }

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

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

1

Bileşen: Şablonda bir eylem oluşturmak yerine tüm yönlendirme olaylarına abone olun ve NavigasyonEnd b / c'yi kaydırın, aksi takdirde bunu kötü navigasyonlarda veya engellenen rotalarda vb. Tetikleyeceksiniz ... Bu, bir rotaya başarıyla gidildi, ardından rahatça kaydırıldı. Aksi takdirde hiçbir şey yapmayın.

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

  router$: Subscription;

  constructor(private router: Router) {}

  ngOnInit() {
    this.router$ = this.router.events.subscribe(next => this.onRouteUpdated(next));
  }

  ngOnDestroy() {
    if (this.router$ != null) {
      this.router$.unsubscribe();
    }
  }

  private onRouteUpdated(event: any): void {
    if (event instanceof NavigationEnd) {
      this.smoothScrollTop();
    }
  }

  private smoothScrollTop(): void {
    const scrollToTop = window.setInterval(() => {
      const pos: number = window.pageYOffset;
      if (pos > 0) {
          window.scrollTo(0, pos - 20); // how far to scroll on each step
      } else {
          window.clearInterval(scrollToTop);
      }
    }, 16);
  }

}

HTML

<router-outlet></router-outlet>

1

bunu dene

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

bu kod açısal 6 destekledi <=

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.