реализовать angular2-virtual-scroll с наблюдаемым в angular4

Я пытаюсь реализовать angular2-virtual-scroll в проекте angular4. Во-первых, может ли кто-нибудь подтвердить, возникнут ли у меня проблемы с его реализацией в NG4. Я не думаю, что должен, и я не видел никаких уведомлений об обратном. Во-вторых, я использую наблюдаемое вместо обещания, показанного в документах NPM angular2-virtual-scroll. Однако, когда я применил тег виртуальной прокрутки, мой вывод не изменился... нет полосы прокрутки... данные из наблюдаемого отображаются, но без прокрутки. Ниже приведены соответствующие сегменты кода:

Home.component.html

<h1 style="color: #76323f">
  {{title}}
</h1>

<h4>
  {{description}}
</h4>
<h2>Coming Soon....</h2>
<app-events-list [upcomingEvents]="upcomingEvents"></app-events-list>

home.component.ts

import {Component, OnInit,OnDestroy } from '@angular/core';
import {UpcomingEvent}       from './../../interface/upcomingevent';
import {EventService}        from './../../services/event.service';
import {Subscription}        from 'rxjs/Subscription';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css']
})

export class HomeComponent implements OnInit, OnDestroy {
  upcomingEvents: Array<UpcomingEvent>;
  title = 'Welcome....';
  description='Events promotions....';
  eventServiceSub: Subscription;

  constructor(private eventService: EventService){
    this.upcomingEvents = [];
  }

  ngOnInit() {
    this.eventServiceSub=this.eventService.getEvents().subscribe(upcomingEvents=>{this.upcomingEvents=upcomingEvents.slice(0,25);
    });
  }
  ngOnDestroy(){
    if (this.eventServiceSub){
      this.eventServiceSub.unsubscribe();
    }
  } 
}

список-событий-component.html

    <virtual-scroll [items]="items" (update)="upcomingEvents = $event"
    (change)="onlistChange($event)">
     <app-upcomingevent *ngFor="let upcomingEvent of upcomingEvents"[upcomingEvent]="upcomingEvent" [eventItemCss]="'event-item'"></app-upcomingevent>
     <div *ngIf="loading" class="loader">Loading.....</div>
    </virtual-scroll>

список-событий-component.ts

import { Component, Input, OnDestroy, OnInit } from '@angular/core';
import { UpcomingEvent } from './../../interface/upcomingevent';
import { trigger,state,style,transition,animate,keyframes } from '@angular/animations';
import { ChangeEvent } from 'angular2-virtual-scroll';
import {EventService}        from './../../services/event.service';
import {Subscription}        from 'rxjs/Subscription';

@Component({
  selector: 'app-events-list',
  templateUrl: './events-list.component.html',
  styleUrls: ['./events-list.component.css'],
  animations: []
})
export class EventsListComponent implements OnInit, OnDestroy {


 @Input()
 upcomingEvents: Array<UpcomingEvent>;

 items=this.upcomingEvents;
 protected buffer: Array<UpcomingEvent> =[];
 protected loading: boolean;
 eventServiceSub: Subscription;


 constructor(private eventService: EventService) { 
    this.upcomingEvents=[];
 }

  ngOnInit() {
  }

  ngOnDestroy(){
    if (this.eventServiceSub){
      this.eventServiceSub.unsubscribe();
    }
  } 

  protected onlistChange(event: ChangeEvent){
    if (event.end !==this.buffer.length) return;
    this.loading=true;

    this.eventServiceSub=this.eventService.getEvents().subscribe(upcomingEvents=>{
         this.buffer=upcomingEvents.slice(this.buffer.length,25);
         this.loading=false;
      }, ()=> this.loading=false);
   }
 }

eventService.ts

import { Injectable } from '@angular/core';
import {UpcomingEvent} from './../interface/upcomingevent'
import {Http} from '@angular/http';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/map';

@Injectable()
export class EventService {

  constructor(private http: Http) { }

  getEvents(): Observable<UpcomingEvent[]>
  {
    return this.http
       .get(`https://jsonplaceholder.typicode.com/posts`)
       .map(response => response.json() as UpcomingEvent[]);

  }
}

upcomingEvents.html

<md-card [ngClass]="'event-item'">
  <h4 [ngClass]="'event-title'" [ngStyle]="{'color':'purple'}"> {{upcomingEvent.title}}</h4>    
   <md-card-actions>
    <button md-button>LIKE</button>
    <button md-button>SHARE</button>
   </md-card-actions>
</md-card>

upcomingEvents.component.ts

import { Component, Input,OnInit } from '@angular/core';
import { UpcomingEvent } from './../../interface/upcomingevent';
@Component({
  selector: 'app-upcomingevent',
  templateUrl: './upcomingevent.component.html',
  styleUrls: ['./upcomingevent.component.css']
})
export class UpcomingeventComponent implements OnInit {

 @Input()
 upcomingEvent: UpcomingEvent;

 @Input()
 eventItemCss: string;

  constructor() { }

  ngOnInit() {
    if (!this.upcomingEvent) {
     this.upcomingEvent=<UpcomingEvent> {}; 
     }

    }

}

Предполагается, что он работает следующим образом: HomeComponent запрашивает данные из eventService через наблюдаемый объект. Затем данные передаются компоненту eventList, где они повторяются, и передаются компоненту предстоящих событий для представления через HTML. Сначала запрашивается 25 событий, и если пользователь прокручивает до конца, еще 25 запрашиваются из службы событий... на этот раз компонентом предстоящих событий. Я не уверен, что это самый эффективный способ сделать это, но в любом случае он не работает. Виртуальная прокрутка, кажется, не влияет на вывод .... Я был бы очень признателен, если бы кто-нибудь показал мне, что я делаю неправильно .... Спасибо.


person MichaelE    schedule 23.05.2017    source источник
comment
Вы думали об использовании библиотеки (например, этой)?   -  person Sergey Sokolov    schedule 24.05.2017
comment
Я взглянул на nix-infinite-scroll, но документация меня не впечатлила. Оказалось написано для продвинутого пользователя. Я новичок в angular, поэтому мне нужна хорошая документация.   -  person MichaelE    schedule 25.05.2017
comment
Также я думаю, что ng2-virtual-scroll подходит в этом контексте.   -  person MichaelE    schedule 25.05.2017
comment
Ok. Насколько я понял, виртуальная прокрутка не запускает событие update. Пожалуйста, включите код этого компонента.   -  person Sergey Sokolov    schedule 25.05.2017
comment
@SergeySokolov, если вы говорите об обновлении отображения до следующего элемента в буфере, то я считаю, что эта строка ‹virtual-scroll [items]=items (update)=upcomingEvents = $event (change)=onlistChange($event)› в event-list-component.html должен это сделать.   -  person MichaelE    schedule 25.05.2017
comment
@SergeySokolov, если вы говорите о получении большего количества данных из API, то это то, что наблюдаемое должно делать в этом фрагменте event-list-component.ts .......this.eventServiceSub=this.eventService.getEvents(). subscribe(upcomingEvents=›{ this.buffer=upcomingEvents.slice(this.buffer.length,25); this.loading=false; }, ()=› this.loading=false);   -  person MichaelE    schedule 25.05.2017
comment
MichaelE, извините, я вас неправильно понял. Когда вы сказали, что either case it doesn't work, вы имели в виду, что не видите первые 25 элементов? У вас служба на самом деле называется? Если вы удалите элемент virtual scroll, будет ли отображаться список событий?   -  person Sergey Sokolov    schedule 25.05.2017
comment
@SergeySokolov Да, я вижу 25 элементов ... так же, как и без виртуальной прокрутки. Да, служба работает ...... как я упоминаю в вопросе ... данные из наблюдаемого отображаются, но нет прокрутки ... нет полосы прокрутки ничего   -  person MichaelE    schedule 27.05.2017
comment
если вы видите элементы, но не видите прокрутку, то, скорее всего, вам нужно установить height из app-events-list элемента.   -  person Sergey Sokolov    schedule 27.05.2017
comment
Если вы хотите использовать Observables, возможно, попробуйте эту реализацию на основе Observable в A4: github.com/dinony/od -virtualscroll Содержит множество примеров!   -  person dinony    schedule 19.06.2017
comment
@dinony .... Я посмотрю отчет, если он сработает ... спасибо за внимание.   -  person MichaelE    schedule 21.06.2017


Ответы (1)


Кажется, я вижу проблему в вашем коде. При использовании виртуальной прокрутки вам нужно сохранить два массива — один для всех загруженных данных и один для отображаемых в данный момент элементов. Похоже, вы их перепутали.

Назовем all-items-array как items, а render-array — как upcomingEvents.

Первый кусок элементов будет передан из родительского компонента, следовательно:

Home.component.html

...
<app-events-list [items]="upcomingEvents"></app-events-list>

event-list-component.html выглядит хорошо

список-событий-component.ts

import { Component, Input, OnDestroy, OnInit } from '@angular/core';
import { UpcomingEvent } from './../../interface/upcomingevent';
import { trigger,state,style,transition,animate,keyframes } from '@angular/animations';
import { ChangeEvent } from 'angular2-virtual-scroll';
import {EventService}        from './../../services/event.service';
import {Subscription}        from 'rxjs/Subscription';

@Component({
  selector: 'app-events-list',
  templateUrl: './events-list.component.html',
  styleUrls: ['./events-list.component.css'],
  animations: []
})
export class EventsListComponent implements OnInit, OnDestroy {


 @Input()
 items: Array<UpcomingEvent> = [];

 upcomingEvents: Array<UpcomingEvent>;

 protected loading: boolean;
 eventServiceSub: Subscription;


 constructor(private eventService: EventService) { 
    this.upcomingEvents=[];
 }

  ngOnInit() {
  }

  ngOnDestroy(){
    if (this.eventServiceSub){
      this.eventServiceSub.unsubscribe();
    }
  } 

  protected onlistChange(event: ChangeEvent){
    if (event.end !==this.items.length) return;
    this.loading=true;

    this.eventServiceSub=this.eventService.getEvents().subscribe(upcomingEvents=>{
         this.items=upcomingEvents.slice(0, this.items.length + 25);
         this.loading=false;
      }, ()=> this.loading=false);
   }
 }

Внимание! код не тестировался, я просто отредактировал ваш код.

person Sergey Sokolov    schedule 26.05.2017
comment
Я проверю и дам вам знать - person MichaelE; 27.05.2017
comment
Тест не дал данных... нет списка. Похоже, мы где-то потеряли данные, полученные от API... Спасибо за ваше предложение. - person MichaelE; 29.05.2017