Я вытаскиваю список аудитории из api. Важное замечание касается только 10 аудиторий на каждую страницу показывает. Другими словами, мне нужно перебирать несколько страниц, чтобы просматривать / проверять информацию для всех аудиторий. Как это сделать?
Вот как теперь выглядит этот вытягивающий список из api:
Список аудитории component.ts:
export class NanoAudienceListComponent implements OnInit {
public audienceListDto: AudienceListDto;
public audienceListDtoData: AudienceListDtoData;
constructor(private audienceModel: AudienceModel,
private modalModel: ModalModel) {
}
public ngOnInit() {
this.getListDto();
this.getListDtoData();
}
private getListDto(): void {
this.audienceListDto = this.audienceModel.getListDto();
}
private getListDtoData(): void {
this.audienceModel
.getListDtoData(this.audienceListDto)
.catch(error => console.info(error))
}
}
Модель аудитории, в которой мы отправляем api req:
@Injectable()
export class AudienceModel extends AbstractEntityModel {
public static ENTITY_NAME: string = 'audience';
public dto: { [key: string]: AudienceDto };
public dtoList: Array<AudienceDto>;
protected entityName = 'Audience';
protected list: AudienceListDto | null = null;
protected service: AudienceService;
constructor(audienceService: AudienceService) {
super(dialogModel, notificationModel, audienceService, errorHandler);
}
public getListDtoDataFromApiByEntity(audienceListDto: AudienceListDto): Promise<any[]> {
return this.service.getList();
}
}
Аудитория:
export class AudienceService {
public getList(...args): Promise<any> {
return this.http
.get(this.listUrl, {headers: this.requestHeaders.getHeaders()})
.toPromise()
.then(response => response.json());
}
}
Список компонентов html:
<nano-table *ngIf = "audienceListDto.isLoaded === true"
[@fadeIn] = "'in'"
[tableList] = "audienceListDto.list"
[columnsArray] = "columnsArray"
[pageCount] = "10"
[sortField] = "'latestGeneralUploadUniqueUsers'"
[sortInverse] = "true">
<ng-template let-audienceListDtoData = "item">
<div class = "nano-table-entity-name-cell">
<span [tooltip] = "audienceListDtoData.name"
[routerLink] = "['/private/audience/' + audienceListDtoData.id]"
class = "nano-c-p">
{{ audienceListDtoData.name }}
</span>
<span>
{{ audienceListDtoData.id }}
</span>
</div>
<div>
<span [hidden] = "audienceListDto.areStatisticsLoaded === false">
{{ audienceListDtoData.dateRange }}
</span>
</div>
Компонент таблицы ts: (эта композиция вызывается в компоненте List, и у них есть родительские дочерние отношенияhp)
export class NanoTableComponent {
@ContentChild(TemplateRef) template: TemplateRef<any>;
@Input() columnsArray: Array<NanoTableHeader> = [];
@Input() isAsync: boolean = false;
@Input() nanoTable: NanoTable;
@Input() pageCount: number = 10;
@Input() pageCountOptions: Array<number> = [5, 10, 20];
@Input() sortField: string | null = null;
@Input() sortInverse: boolean = false;
@Input() useQueryParams: boolean = true;
@Input() hasExport: boolean = false;
@Input()
public set tableList(value: Array<any>) {
this._tableList = value;
this.onTableListChange();
}
public get tableList(): Array<any> {
return this._tableList;
}
@Output() paginationChange = new EventEmitter();
@Output() exportRequest = new EventEmitter();
public isExportInProgress: boolean = false;
public isLoadingAsync: boolean = false;
public pageNumber: number = 1;
public searchWord: string = '';
private _tableList: Array<any> = [];
constructor(private router: Router,
private activatedRoute: ActivatedRoute) {
}
public getFilteredList() {
if (this.isAsync === true) {
return this._tableList.slice(0, this.pageCount);
}
if (this.pageNumber > Math.ceil(this.filterListBySearchWord().length / this.pageCount)) {
this.pageNumber = 1;
}
return this.filterListBySearchWord().slice((this.pageNumber - 1) * this.pageCount, (this.pageNumber - 1) * this.pageCount + this.pageCount);
// TODO: Change this.
}
public getLengthForFooter(): number {
if (this.isAsync) {
return this.nanoTable.total;
} else {
if (this.searchWord) {
return this.filterListBySearchWord().length;
}
return this.tableList.length;
}
}
public exportReport(): void {
this.isExportInProgress = true;
this.exportRequest.emit();
}
public onPageCountChange(pageCount: number): void {
if (this.isAsync === false) {
this.pageCount = pageCount;
// this.filterList();
} else {
this.nanoTable.pageCount = pageCount;
}
this.onPaginationChange();
}
public onPageNumberChange(pageNumber: number): void {
if (this.isAsync === false) {
this.pageNumber = pageNumber;
// this.filterList();
} else {
this.nanoTable.pageNumber = pageNumber;
}
this.onPaginationChange();
}
public onSortFieldChange(sortFiled: string) {
if (this.isAsync === false) {
this.sortField = sortFiled;
if (this.sortField === sortFiled) {
this.sortInverse = !this.sortInverse;
}
this.handleColumnSorting(this.sortField);
} else {
this.nanoTable.sortField = sortFiled;
if (this.nanoTable.sortField === sortFiled) {
this.nanoTable.sortInverse = !this.nanoTable.sortInverse;
}
}
this.onPaginationChange();
}
private checkAreQueryParamsValid(): boolean {
return Object.keys(this.getQueryParams()).includes('pageCount');
// TODO: Fix this.
}
private filterListBySearchWord(): Array<any> {
if (!this.searchWord) {
return this._tableList;
}
let keys: Array<string> = Object.keys(this.tableList[0]);
return this._tableList.filter((value: { [key: string]: string | number | null }) => {
for (let i = 0; i < keys.length; i++) {
if (value[keys[i]] && value[keys[i]].toString().toLowerCase().includes(this.searchWord.toLowerCase())) {
return true;
}
}
return false;
});
}
private getQueryParams(): Params {
return this.activatedRoute.snapshot.queryParams;
}
private handleColumnSorting(column: string): void {
if (column === null) {
return;
}
let compare = this.sortInverse ? compareReversed : compareNormal;
function compareNormal(a, b) {
if (a[column] === null) {
return 1;
}
if (b[column] === null) {
return -1;
}
if (a[column] < b[column]) {
return -1;
}
if (a[column] > b[column]) {
return 1;
}
return 0;
}
function compareReversed(a, b) {
if (a[column] === null) {
return -1;
}
if (b[column] === null) {
return 1;
}
if (a[column] > b[column]) {
return -1;
}
if (a[column] < b[column]) {
return 1;
}
return 0;
}
this._tableList.sort(compare);
}
private onPaginationChange(): void {
this.setQueryParams();
if (this.isAsync) {
this.isLoadingAsync = true;
this.paginationChange.emit(this.nanoTable);
}
}
private onTableListChange(): void {
if (this.isAsync === true) {
this.setTableParams();
} else {
this.setFromQueryParams();
this.handleColumnSorting(this.sortField);
}
}
private setFromQueryParams(): void {
if (this.useQueryParams === true && this.checkAreQueryParamsValid()) {
const queryParams = this.getQueryParams();
this.pageCount = parseInt(queryParams['pageCount'], 10);
this.pageNumber = parseInt(queryParams['pageNumber'], 10);
this.sortField = queryParams['sortField'];
this.sortInverse = queryParams['sortInverse'] === 'true';
}
}
}
HTML-часть табличного компонента:
div *ngIf = "tableList.length > 0"
class = "nano-table-grid nano-mt-5">
<div class = "nano-f-r">
<input type = "text" [(ngModel)] = "searchWord" class = "nano-white-smoke-input" placeholder = "Search"/>
<button *ngIf = "hasExport === true && isExportInProgress === false"
type = "button"
class = "nano-f-250 nano-white-smoke-button nano-ml-2"
(click) = "exportReport()">
<span>
CSV
</span>
</button>
<nano-loading-indicator *ngIf = "isExportInProgress === true"
class = "nano-loading-bar-small nano-loading-bar-overlay nano-f-250 "
style = "margin-left: 2px"></nano-loading-indicator>
</div>
<div class = "nano-table-row nano-table-grid-header">
<div class = "{{column.columnClass}}"
*ngFor = "let column of columnsArray"
[ngClass] = "{'sort-active':sortField === column.columnField}"
(click) = "onSortFieldChange(column.columnField)">
<span>
{{column.columnName}}
</span>
<i class = "fa"
[class.fa-sort-asc] = "sortInverse === true && sortField === column.columnField"
[class.fa-sort-desc] = "sortInverse === false && sortField === column.columnField">
</i>
</div>
</div>
Где взять количество страниц?
@TheUnreal Я не знаю. В таблице, в которой я должен представить эти данные, по умолчанию 10 элементов на странице.
@Shilly Я думаю, что у меня нет этого параметра api на api, на котором я могу указать диапазон страниц. Но сейчас проверю.
@Shilly Можно ли изменить текущую реализацию на ту, где я буду перебирать несколько страниц? Потому что вообще проблема в том, что в этом списке аудитории отсутствует пара аудиторий. И я исследую, в чем может быть проблема. Я обнаружил, что это решение может быть итерацией через API с несколькими страницами.
Я не знаю, все зависит от того, что предлагает вам API, который вы используете. То, что вы описываете, является простым циклом или параметром, который вы должны добавить, чтобы это было вполне возможно, но без дополнительной информации я не знаю, что может делать API или какие изменения необходимо внести, чтобы использовать API. Поэтому, если вы не свяжете нас с документацией по API, мы не сможем сказать, какие строки кода нужно изменить. Если он ограничен 10 результатами на запрос, ДОЛЖЕН быть параметр или другой механизм для разбивки данных на страницы, иначе API не работает. Но если это this.listUrl + '&page=4' или this.listURL + '&range=4-5', то только вы можете нам сказать.
@Shilly Хорошо, спасибо! В настоящее время у меня не так много информации, но вы помогли мне здесь лучше понять, что мне нужно делать.
@Shilly, хорошо, спасибо! Мне нужно время, чтобы разобраться.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


У API нет параметров, в которых можно указать диапазон страниц? Если всегда ровно 10 результатов, можете ли вы это изменить? Если у вас нет контроля над API, откуда вы знаете, что достигли последней аудитории в коллекции?