首页 > 解决方案 > 如何迭代多个页面的 API?

问题描述

我正在从 api中提取受众列表。需要注意的重要一点是每页节目只有大约 10 个观众。换句话说,我必须遍历多个页面才能查看/检查所有受众的信息。这个怎么做?

下面是这个从 api 提取的列表现在的样子:

观众列表组件.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.log(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:(此组件在列表组件上调用,并且它们具有父子关系)

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>

标签: javascriptangulartypescript

解决方案


推荐阅读