Отслеживание положения прокрутки и уведомление об этом других компонентах
Есть ли простой способ отслеживать положение прокрутки браузера и уведомлять об этом больше, чем один компонент.
Случай использования: в прокрутке я хочу иметь возможность изменять классы различных элементов на странице, основываясь на том, где я. В предыдущей версии angular это было несколько возможно через плагин afix (тот же для jQuery). Разумеется, есть возможность написать незавершенную JS, инициализировать его при запуске приложения и испустить событие. Звучит грязно, и эмиссия событий довольно дорога для этого типа вещей.
Каковы мои варианты здесь?
ОБНОВЛЕНИЕ (после предложений):
Итак, вот что я пробовал:
Я создал компонент:
import {Component} from "angular2/core";
@Component({
selector: '[track-scroll]',
host: {'(window:scroll)': 'track($event)'},
template: ''
})
export class TrackScrollComponent {
track($event) {
console.debug("Scroll Event", $event);
}
}
добавлен атрибут главной директивы приложения:
<priz-app track-scroll>
И добавил компонент как один из поставщиков в верхнем компоненте:
import {TrackScrollComponent} from "../../shared/components/track-scroll.component";
@Component({
selector: 'priz-app',
moduleId: module.id,
templateUrl: './app.component.html',
directives: [ROUTER_DIRECTIVES, SecureRouterOutlet, AppHeader, TrackScrollComponent],
providers: [AuthenticationService]
})
Все еще ничего...
Другое обновление:
Перемещено track-scroll
в один из элементов div основного шаблона:
<div class="container-fluid" track-scroll>
<div class="row">
<div class="col-md-12">
<app-header></app-header>
<secure-outlet signin="Login" unauthorized="AccessDenied"></secure-outlet>
</div>
</div>
</div>
И теперь приложение загружается с полностью пустым экраном.
FUN FUN FUN...
ЗАКЛЮЧИТЕЛЬНОЕ РЕШЕНИЕ (это сработало для меня).
import {Directive} from "angular2/core";
@Directive({
selector: '[track-scroll]',
host: {'(window:scroll)': 'track($event)'}
})
export class TrackScrollDirective {
track($event: Event) {
console.debug("Scroll Event", $event);
}
}
- Добавьте его как директиву в любое место, где оно используется:
directives: [TrackScrollDirective]
- Добавить атрибут в любой элемент, где мы хотим отслеживать событие:
<div class="col-md-12" track-scroll>
Ответы
Ответ 1
Я думаю, что самый простой способ - это любой заинтересованный компонент, который прослушивает событие прокрутки.
@Component({
...
// alternative to `@HostListener(...)`
// host: {'(window:scroll)': 'doSomething($event)'}
})
class SomeComponent {
@HostListener('window:scroll', ['$event'])
doSomething(event) {
// console.debug("Scroll Event", document.body.scrollTop);
// see András Szepesházi comment below
console.debug("Scroll Event", window.pageYOffset );
}
}
plunker
Plunker с помощью @HostListener()
Подсказка:
bootstrap(MyComponent, [
provide(PLATFORM_DIRECTIVES, {useValue: [TrackScrollDirective], multi:true})]);
делает директиву универсально, не добавляя ее в список всех компонентов directive: [...]
.
Ответ 2
Я был вынужден решить это по-другому, потому что мне нужно было посмотреть несколько прокручиваемых элементов в окне. Я создал директиву для просмотра положения прокрутки элемента:
@Directive({
selector: '[scroll]'
})
export class ScrollDir {
@Output() setScroll = new EventEmitter();
private scroll: number;
constructor(private el: ElementRef) { }
@HostListener('scroll', ['$event'])
scrollIt() { this.scroll = event.srcElement.scrollTop }
reset() { this.el.nativeElement.scrollTop = this.scroll }
}
Затем на любом компоненте, содержащем элемент прокрутки, который нуждался в этом элементе, я мог бы @ViewChild
директивой следующим образом:
@Component({
selector: 'parent',
template: `
<div class="container" scroll>
// *ngFor=""...
</div>
`
})
export class ParentComp implements AfterViewChecked {
@ViewChild(ScrollDir) scroll: ScrollDir;
ngAfterViewChecked() {
this.scroll.reset()
}
}