Здравствуйте, в этом случае я бы, вероятно, использовал рекурсивную стратегию, такую как thie CodeSandbox , демо использует Subject.
Вот фрагмент кода со структурой рекурсивного элемента, за которым следуетфиктивная служба запросов для фида данных.
В общем, я просто вызываю один и тот же элемент всякий раз, когда Subject
в моем сервисе обновляется с .next()
, хитрая часть такова, чтовы должны использовать pipe(first())
для вашей темы подписки , потому что в противном случае подписка не будет отменена, даже если вы добавили логику отмены подписки в onDestroy
(уничтожить не вызов, потому что на самом деле выпросто погружайтесь все больше и больше в рекурсию без отсоединения какого-либо компонента), и это нарушит вашу логику визуализации.
// Typescript
import { Component, Input } from "@angular/core";
import { InfinityScrollFeedService } from "./../services/infinity-scroll-feed.service";
import { first } from "rxjs/operators";
@Component({
selector: "app-recursive",
templateUrl: "./recursive.component.html",
styleUrls: ["./recursive.component.css"]
})
export class RecursiveComponent {
@Input() initialData;
@Input() page;
nextLayer = [];
constructor(private feed: InfinityScrollFeedService) {}
ngOnInit() {
this.feed.httpCallMocker.pipe(first()).subscribe(data => {
this.nextLayer = data;
});
}
loadMore() {
this.feed.retrivePackage(Number(this.page) + 1);
}
}
// Template
<div class="row" *ngFor="let row of initialData">
<div>Name: {{row.name}}</div>
<div>Age: {{row.age}}</div>
</div>
<div *ngIf="nextLayer.length > 0">
<app-recursive [initialData]="nextLayer" [page]="(page+1)">
</app-recursive>
</div>
<button *ngIf="nextLayer.length <= 0" (click)="loadMore()">Show more</button>
// Css
.row {
display: flex;
justify-content: space-between;
border: 1px solid red;
}
import { Injectable } from "@angular/core";
import { Subject } from "rxjs";
@Injectable()
export class InfinityScrollFeedService {
dataPackages = [];
someMokeNames = ["Hari", "Xapu", "Hristiyan", "Pesho", "Gosho", "Ivan"];
httpCallMocker = <[]>new Subject();
constructor() {}
private getRandomNumber = max => {
return Math.floor(Math.random() * Math.floor(max));
};
private addDataPackage = () => {
let newData = [];
for (let i = 0; i < 10; i++) {
newData.push({
name: this.someMokeNames[
this.getRandomNumber(this.someMokeNames.length - 1)
],
age: this.getRandomNumber(100)
});
}
this.dataPackages.push(newData);
};
retrivePackage(page) {
if (this.dataPackages.length <= page) {
this.addDataPackage();
}
this.httpCallMocker.next(this.dataPackages[page]);
}
}