我有一个Ionic 4应用程序,正在从API中提取数据。该页面具有无限滚动的项目列表。现在,我想添加一个搜索功能,该功能将使用搜索到的项目更新结果集,并且如果搜索结果中有10个以上的项目,则在必要时仍具有无限滚动功能。
使用下面的代码,我可以查看艺术家并无限滚动地加载更多作品。当我按名称搜索时,会显示正确的结果,但它会尝试加载不带搜索词的项目端点的页面2,而不是加载搜索词具有10个以上结果的帖子的第二页。
我可以在执行loadItems函数时检查searchTerm是否具有值,但这似乎是错误的。
如果搜索结果少于10个,如何更新项目并停止执行无限滚动?
如果有10个以上的结果,如何用搜索端点触发inifinte滚动?
我觉得我可能没有充分利用可观察物的潜力或在这里使用不正确,但是我仍在学习它们,所以如果我愿意,那就轻松些。
我的代码在下面
Items.html
<ion-content padding>
<ion-searchbar [(ngModel)]="searchTerm" (ionChange)="searchChanged($event)"></ion-searchbar>
<ion-grid *ngIf="items">
<ion-row>
<ion-col *ngFor="let item of items">
<app-item-card [item]="item"></app-item-card>
</ion-col>
<ion-infinite-scroll threshold="100px" (ionInfinite)="loadItems($event)">
<ion-infinite-scroll-content loadingSpinner="bubbles" loadingText="Loading more items...">
</ion-infinite-scroll-content>
</ion-infinite-scroll>
</ion-row>
</ion-grid>
</ion-content>
Items.page.ts
import { ItemsService } from '../../services/items.service';
import { Item } from '../../models/item.model';
@Component({
selector: 'app-items',
templateUrl: './items.page.html',
styleUrls: ['./items.page.scss'],
})
export class ItemsPage implements OnInit {
public items: Item[] = [];
public searchTerm: string = '';
constructor(private itemsService: ItemsService) {}
async ngOnInit() {
this.getItems().subscribe(data => {
this.items = data;
});
}
getItems() {
return this.itemsService.getItems();
}
loadItems(event) {
// Calculate the page number to request based on the number of posts
let page = (Math.ceil(this.items.length / 10)) + 1;
this.itemsService.getItems(page).subscribe(data => {
for (let post of data) {
this.items.push(post);
}
event.target.complete();
if (data.length < 10) {
event.target.disabled = true;
}
});
}
searchChanged() {
if (this.searchTerm) {
this.itemsService.searchItems(this.searchTerm).subscribe(data => {
this.items = data;
});
}
}
}
ItemsService.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, forkJoin, of, empty } from 'rxjs';
import { catchError, map, flatMap } from 'rxjs/operators';
import { Item} from '../../models/item.model';
@Injectable({
providedIn: 'root'
})
export class ItemsService {
private apiUrl: string = appConfig.apiUrl;
constructor(private httpClient: HttpClient) { }
getItems(page: number = 1): Observable<Item[]> {
let url = this.apiUrl + 'items/?&page=' + page;
return this.httpClient.get(url).pipe(
map(items => {
let itemsArray = [];
Object.keys(items).forEach(function (key) {
itemsArray.push(new Item(items[key]));
});
return itemsArray;
}),
catchError(val => of(val))
);
}
searchItems(term: string, page: number = 1) {
let url = this.apiUrl + 'items/?page=' + page + '&name=' + encodeURI(term);
return this.httpClient.get(url).pipe(
map((items: Item[]) => {
let itemsArray = [];
Object.keys(items).forEach(function (key) {
itemsArray.push(new Item(items[key]));
});
return itemsArray;
}),
catchError(val => of(val))
);
}
}
Item.model.ts
export class Item {
id: number;
name: string;
constructor(values: Object = {}) {
Object.assign(this, values);
}
}