如何在Ionic 4应用程序中使用搜索结果数据更新可观察对象

时间:2019-05-14 11:13:18

标签: ionic-framework observable

我有一个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);
    }
}

0 个答案:

没有答案