我从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.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 :(此comp在List组件上调用,它们具有父子关系)
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>