2016-03-24 4 views
22

У меня проблема с Angular 2, где переход с одного маршрута на другой автоматически не прокручивается до вершины нового вида. Я понимаю, что Angular 1 разрешил добавлять свойство autoscroll в элемент HTML, а другие придумали какой-то простой javascript (например, window.scroll(0, 0)), чтобы заставить виды прокручивать вверх при загрузке.Autoscroll in Angular 2

Однако я не уверен, как это сделать с помощью Angular 2. Кто-нибудь знает, как этого достичь?

ответ

17

обновление

В настоящее время не существует автоматического способа.

Смотрите также Angular 2 typescript error when using subscribe function on new router (rc 1)

Смотрите также https://github.com/angular/angular/issues/6595#issuecomment-244232725

class MyAppComponent { 
    constructor(router: Router) { 
    router.events.subscribe(s => { 
     if (s instanceof NavigationEnd) { 
     const tree = router.parseUrl(router.url); 
     if (tree.fragment) { 
      // you can use DomAdapter 
      const element = document.querySelector("#" + tree.fragment); 
      if (element) { element.scrollIntoView(element); } 
     } 
     } 
    }); 
    } 
} 

обновление

В новом маршрутизаторе V3-beta.2 вы можете передать фрагмент с маршрутизаторами и ссылки маршрутизатор навигация

<a [routerLink]="..." fragment="top"> 

он должен перейти к нему, но и добавляет #top к URL (не тестировался себя еще)

Update

Оригинал

Существует открытый вопрос покрытия этого https://github.com/angular/angular/issues/6595

Обходной путь (упомянутый в https://github.com/angular/angular/issues/6946)

Инжектируйте маршрутизатор, подписаться на изменения маршрута и вызвать свиток вверх:

> = RC.x

router.changes.subscribe() => { 
    window.scrollTo(0, 0); 
}); 

бета

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

Этот обходной путь будет достаточно для теперь, спасибо! –

+1

@ GünterZöchbauer, как я могу это сделать в RC5? Пожалуйста, дайте мне знать – user1354934

+0

В чем проблема? Это должно работать одинаково. –

4

Я имел такой же выпуск. Основываясь на ответе Гюнтера, я обнаружил, что новый маршрутизатор Angular 2 RC.1 не обеспечивает непосредственное наблюдение. Вместо этого у этого объекта есть свойство changes. Обойти RC.1 является:

this._router.changes.subscribe(() => { 
    window.scrollTo(0, 0); 
}); 
+0

Я предпочитаю этот ответ, так как код действительно компилируется (другой ответ отсутствует), и я также вводю маршрутизатор в качестве частного участника, который должен быть обычной практикой. – hartz89

9

Нового РЦ (> = RC.3), похоже, не подвергать changes Observable, это, вероятно, с тех пор было переименовано в events или routerEvents.

Их совершенно «фантастические» документы, похоже, не предоставляют никакой информации о том, что делает что-то, поэтому я думаю, что у вас есть небольшая русская рулетка. Или переверните монету или что-то еще.

От this ответа, кажется, events Observable возвращает события относительно навигационного состояния:

router.events.subscribe(event:Event => { 
    if(event is NavigationStart) { 
    } 
    // NavigationEnd 
    // NavigationCancel 
    // NavigationError 
    // RoutesRecognized 
    } 
+0

Согласен. Я рекомендую использовать NavigationEnd в качестве триггера для прокрутки –

1

Для тех из вас, кто находит window.scrollTo(0,0) не работает (я предполагаю, что из-за материального дизайна sidenav но полностью угадывая) используйте метод, который находится здесь: Javascript/CSS window.scrollTo(0,0) not working

+0

URL-адрес не работает. –

+0

Добрый Угадай! Причина window.scrollTo() не работает, потому что вы не хотите прокручивать окно, если используете <роутер-выход>, вы хотите прокрутить элемент содержимого внутри вашего <маршрутизатора-выхода>. См. Ответ Тайсона. – rbj325

4

Я использовал if (this.router.navigated) в ngOnInit каждой страницы для определения ine использовать или не использовать window.scrollTo (0, 0). Это будет охватывать большинство случаев маршрутизации на страницу, оставляя положение прокрутки, где оно должно быть, если вы нажмете кнопку «Назад в браузере».

if(this.router.navigated) { 
    window.scrollTo(0, 0); 
} 
13

Has вы можете увидеть здесь: https://angular.io/docs/ts/latest/api/router/index/Router-class.html#!#events-anchor, вы должны использовать «router.events.subscribe», так как углового 2.0.0

Так хорошее решение автоматически приборы типа СПИРАЛЬНЫМИ к вершине всех страниц являются имеют AppComponent так:

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

@Component({ 
    selector: 'app-root', 
    templateUrl: './app.component.html' 
}) 
export class AppComponent { 
    constructor(private router: Router) { 
     router.events.subscribe((val) => { 
      if (val instanceof NavigationEnd){ 
       window.scrollTo(0,0); 
      } 
     }); 
    } 
} 
+0

Спасибо !!!! Ваше решение лучше всего здесь! – neoswf

+0

Действительно, элегантный! – irhetoric

3

100% раствор проверено мной:

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

    } 
1

Я используя материал sidenav, и я не мог получить ни один из предложенных ответов для работы для меня. Вот мой рабочий раствор:

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

... 

constructor(
    private router: Router, 
) { 
    router.events.subscribe(event => { 
    if (event instanceof NavigationEnd) { 
     document.querySelector('.mat-sidenav-content').scrollTop = 0; 
    } 
    } 
} 
1

Вместо написания кода в каждом компоненте, я добавил следующий код в одном месте -

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

    onActivate(e) { 
     window.scrollTo(0, 0); 
    } 
2

Я отправил это в issue thread, но я отправлю его снова Вот.

Моя команда использует what the angular team uses on this repo на угловой.io. Просто сделайте услугу и введите ее как обычно. Затем, на ngAfterViewInit на каждой странице вы хотите это поведение, просто вызовите это. [Scroll service variable name] .scrollToTop(). И, наконец, вам нужно добавить это к вершине <body> в index.html: <div id="top-of-page"></div>

Service Код:

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(/^#/, ''); 
    } 
}