Я использую «angular2-virtual-scroll» для реализации загрузки по требованию. Раньше элементы управлялись наблюдаемыми с использованием асинхронного канала, запускаемого родительским компонентом. Теперь я пытаюсь вызвать свой сервис из ребенка. Вызов успешен, и я получаю свои данные, мне нужно использовать событие подписки, чтобы применить другую логику. Проблема заключается в том, что обнаруженные изменения не работают, когда я обновляю свои массивы в функции подписки. Я читал другие подобные проблемы, но мне не повезло найти решение.
Это основной компонент, в котором используются сервисные вызовы. Первоначальный запрос выполняется из onInit. И затем, когда вы прокручиваете вниз, вызывается fetchMore.
import { Component, OnInit, Input, OnDestroy } from '@angular/core';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';
import { User } from './../models/user';
import { Role } from './../../roles/models/role';
import { UsersService } from './../services/users.service';
import { ChangeEvent } from 'angular2-virtual-scroll';
import { promise } from 'selenium-webdriver';
import { VirtualScrollComponent } from 'angular2-virtual-scroll';
import { Subscription } from 'rxjs/Subscription';
@Component({
selector: 'app-users-list',
template: `
<div class="status">
Showing <span class="">{{indices?.start + 1}}</span>
- <span class="">{{indices?.end}}</span>
of <span class="">{{users?.length}}</span>
<span>({{scrollItems?.length}} nodes)</span>
</div>
<virtual-scroll [childHeight]="75" [items]="users" (update)="scrollItems = $event" (end)="fetchMore($event)">
<div #container>
<app-user-info *ngFor="let user of scrollItems" [roles]="roles" [user]="user">
<li>
<a [routerLink]="['/users/edit/', user.id]" class="btn btn-action btn-edit">Edit</a>
</li>
</app-user-info>
<div *ngIf="loading" class="loader">Loading...</div>
</div>
</virtual-scroll>
`
})
export class UsersListComponent implements OnInit, OnDestroy {
users: User[] = [];
@Input() roles: Role[];
currentPage: number;
scrollItems: User[];
indices: ChangeEvent;
readonly bufferSize: number = 20;
loading: boolean;
userServiceSub: Subscription;
constructor(private usersService: UsersService) {
}
ngOnInit() {
this.reset();
}
ngOnDestroy() {
if(this.userServiceSub) {
this.userServiceSub.unsubscribe();
}
}
reset() {
this.loading=true;
this.currentPage = 1;
this.userServiceSub = this.usersService.getUsers(this.currentPage).subscribe(users => {
this.users = users;
});
}
fetchMore(event: ChangeEvent) {
if (event.end !== this.users.length) return;
this.loading=true;
this.currentPage += 1;
this.userServiceSub = this.usersService.getUsers(this.currentPage).subscribe(users => {
this.users = this.users.concat(users);
});
}
}
Из того, что я прочитал, это может быть проблема контекста, но я не уверен. Любые предложения были бы замечательными.
"РЕДАКТИРОВАТЬ"
Глядя на исходный код компонента плагина, я вижу, где фиксируется событие изменения.
VirtualScrollComponent.prototype.ngOnChanges = function (changes) {
this.previousStart = undefined;
this.previousEnd = undefined;
var items = changes.items || {};
if (changes.items != undefined && items.previousValue == undefined || (items.previousValue != undefined && items.previousValue.length === 0)) {
this.startupLoop = true;
}
this.refresh();
};
Если я поставлю точку останова в этом событии, она сработает при начальной загрузке, поэтому, когда мы создаем экземпляр массива в []. Он срабатывает, когда я нажимаю на страницу. Но он не срабатывает, когда массив обновляется в событии подписки. Я даже поместил кнопку, которая устанавливает пустой массив и обновляет представление, поэтому функция подписки должна нарушать обнаружение изменений.