Angular 4 / Material 2:滚动事件未触发

时间:2017-11-01 15:37:38

标签: javascript angular dom angular-material2

我正在尝试检测何时在我的Angular 4应用程序中滚动窗口,但是当将onscroll事件直接附加到<body>时,事件似乎无法触发元素,或在我的组件中沿着这些行使用某些东西:

this.eventSubscription = Observable.fromEvent( winRef.nativeWindow, "scroll" ).subscribe( e => {
  // do something
} );

网上有各种各样的帖子,但似乎并不是一个明确的答案。一篇文章建议,如果组件在Native范围内,则必须在父元素上将封装设置为<router-outlet>。我试过这个:没有工作,它毁了我的材料组件。

我的组件模板如下所示:

<!-- home.component.html -->
<div>
    <p *ngFor="let item of playlistItems$ | async">
        {{ item | json }}
    </p>
</div>

组件本身:

// home.component.ts  
@Component( {
    selector: 'beyond-home',
    templateUrl: './home.component.html',
    styleUrls: [ './home.component.scss' ]
} )
export class HomeComponent {

    playlistItems$: Observable<Array<IPlaylistItem>>;
    eventSubscription;

    constructor( private store: Store<fromRoot.IState>, private winRef: WindowRef ) {
        this.store.dispatch( playlist.loadPlaylist() );
        this.playlistItems$ = this.store.select( fromRoot.getPlaylistItems );

        this.eventSubscription = Observable.fromEvent( winRef.nativeWindow, "scroll" ).subscribe( e => {
            // do something
        } );
    }
}

我的生活不能解决正在发生的事情。事件并没有被解雇!我正在使用Material 2,这可能会增加复杂性。我甚至订阅了正确的活动吗?真的是window:scroll吗?我有错误的结束吗?

2 个答案:

答案 0 :(得分:0)

我认为在您的代码中您只需要:

  @HostListener('window:scroll', ['$event'])
  onScroll(event) {
    console.log('You scrolled!');
  }

将此添加到组件对我有用。注意添加到正文可能不起作用,因为它不是您的应用程序的一部分。我也在使用材料,并且没有上述代码的副作用。

在这里查看plunkr:

https://plnkr.co/edit/no6czB

您需要显示控制台,以便查看结果。

答案 1 :(得分:0)

尝试异步加载表条目时遇到了同样的问题。最后,使用指令捕获滚动事件工作得很好,它也是可重用的。我没有在&lt; body&gt;上使用它但我猜测如果你把所有东西都包在一个&lt; div&gt;并在那里应用指令它将工作正常。这是我的指示:

import { Directive, HostListener, Output, EventEmitter } from 

'@angular/core';

@Directive({
  selector: '[rzScrollTracker]'
})
export class ScrollTrackerDirective {
  @Output() updateLoad: EventEmitter<any> = new EventEmitter();

  previousValue = 0;
  scrollDir: string = undefined;

  @HostListener('scroll', ['$event'])
  onScroll(event) {
    const tracker = event.target;
    if(tracker.scrollTop > this.previousValue) {
      this.scrollDir = 'down';
    } else {
      this.scrollDir = 'up';
    }
    // console.log('scrollDir:', this.scrollDir);

    let limit = tracker.scrollHeight - tracker.clientHeight;
    // console.log(event.target.scrollTop, limit);
    if (event.target.scrollTop === limit) {
      // console.log('end reached');
      this.updateLoad.emit(true);
    }
    else if (event.target.scrollTop <= Math.floor(limit / 8) && this.scrollDir === 'up') {
      // console.log('scrolled to top');
      this.updateLoad.emit(false);
    }
    this.previousValue = tracker.scrollTop;
  }

  constructor() { }

}

我也在跟踪卷轴的方向,但你不必这样做。 然后,您可以在任何其他元素/组件上使用该指令。我在tbody元素和div上成功使用了它:

<tbody rzScrollTracker (updateLoad)="updateLoadFactor(nestedFilter, $event)"
      <tr *ngFor="let row of filteredResultsInView[nestedFilter]['values']; let j = index">
        <div class="checkbox">
          <input type="checkbox" 
            [value]="row.toString()" 
            [disabled]="!areEnabledFromView[nestedFilter]"
            id="checkrads_{{nestedFilter}}_{{i}}_{{j}}" 
            [checked]="selectedResultsObj[nestedFilter][row.toString()]"
            #cbox
            (click)="selectClickedElement(nestedFilter, cbox)">
          <label for="checkrads_{{nestedFilter}}_{{i}}_{{j}}">{{ row.toString() }}</label>
        </div>      
      </tr>
      <tr> &nbsp;</tr>
      <tr *ngIf="resultsInProgress[nestedFilter]">
        Fetching results...
      </tr>
    </tbody>

指令发出的'updateLoad'事件在组件中捕获,并调用函数来修改显示的数据。我希望这有帮助!