Autoscroll in Angular 2

后端 未结 10 1195
清歌不尽
清歌不尽 2020-12-01 12:21

I\'m experiencing an issue with Angular 2 where changing from one route to another does not automatically scroll to the top of the new view. I realize that Angular 1 allowed

10条回答
  •  夕颜
    夕颜 (楼主)
    2020-12-01 12:42

    I posted this in the issue thread, but I'll post it again here.

    My team has been using what the angular team uses on this repo on angular.io. Just make a service and inject it like usual. Then, on ngAfterViewInit on each page you want this behavior, just call this.[scroll service variable name].scrollToTop(). Finally, you'll need to add this to the top of in index.html:

    Service Code:

    import { Injectable, Inject } from '@angular/core';
    import { PlatformLocation } from '@angular/common';
    import { DOCUMENT } from '@angular/platform-browser';
    import {fromEvent} from 'rxjs/observable/fromEvent';
    
    export const topMargin = 16;
    /**
     * A service that scrolls document elements into view
     */
    @Injectable()
    export class ScrollService {
    
      private _topOffset: number | null;
      private _topOfPageElement: Element;
    
      // Offset from the top of the document to bottom of any static elements
      // at the top (e.g. toolbar) + some margin
      get topOffset() {
        if (!this._topOffset) {
          const toolbar = this.document.querySelector('md-toolbar.app-toolbar');
          this._topOffset = (toolbar && toolbar.clientHeight || 0) + topMargin;
        }
        return this._topOffset;
      }
    
      get topOfPageElement() {
        if (!this._topOfPageElement) {
          this._topOfPageElement = this.document.getElementById('top-of-page') || this.document.body;
        }
        return this._topOfPageElement;
      }
    
      constructor(
          @Inject(DOCUMENT) private document: any,
          private location: PlatformLocation) {
        // On resize, the toolbar might change height, so "invalidate" the top offset.
        fromEvent(window, 'resize').subscribe(() => this._topOffset = null);
      }
    
      /**
       * Scroll to the element with id extracted from the current location hash fragment.
       * Scroll to top if no hash.
       * Don't scroll if hash not found.
       */
      scroll() {
        const hash = this.getCurrentHash();
        const element: HTMLElement = hash
            ? this.document.getElementById(hash)
            : this.topOfPageElement;
        this.scrollToElement(element);
      }
    
      /**
       * Scroll to the element.
       * Don't scroll if no element.
       */
      scrollToElement(element: Element) {
        if (element) {
          element.scrollIntoView();
    
          if (window && window.scrollBy) {
            // Scroll as much as necessary to align the top of `element` at `topOffset`.
            // (Usually, `.top` will be 0, except for cases where the element cannot be scrolled all the
            //  way to the top, because the viewport is larger than the height of the content after the
            //  element.)
            window.scrollBy(0, element.getBoundingClientRect().top - this.topOffset);
    
            // If we are very close to the top (<20px), then scroll all the way up.
            // (This can happen if `element` is at the top of the page, but has a small top-margin.)
            if (window.pageYOffset < 20) {
              window.scrollBy(0, -window.pageYOffset);
            }
          }
        }
      }
    
      /** Scroll to the top of the document. */
      scrollToTop() {
        this.scrollToElement(this.topOfPageElement);
      }
    
      /**
       * Return the hash fragment from the `PlatformLocation`, minus the leading `#`.
       */
      private getCurrentHash() {
        return this.location.hash.replace(/^#/, '');
      }
    }
    

提交回复
热议问题