Filtering an observable in Angular/Nativescript

做~自己de王妃 提交于 2019-12-11 14:32:50

问题


Currently, I'm trying to build an app which retrieves an obserable, which you can then sort and/or filter in some predefined ways.

Retrieving and sorting the data works fine:

sort.service.ts

import { Injectable } from "@angular/core"
import { HttpClient, HttpErrorResponse } from "@angular/common/http"
import { Observable } from "rxjs/Observable";
import { Subscriber } from "rxjs";
import "rxjs/add/operator/catch";
import "rxjs/add/operator/do";
import "rxjs/add/operator/map";
import { Property } from "../property/property.model";
import { UserSettings } from "../../data/usersettings/usersettings.service"

export class SortService {
    url = "/path/to/file.json";

    constructor(private http:HttpClient) {}

    getProperties(): Observable<Property[]> {
        return this.http.get<Property[]>(this.url);
    }
    sortAllProperties() {
        let count = 0;

        return this.getProperties()
        .map((data) => {        
            data.sort((a: Property, b: Property) => {
                const aP = a.price;
                const bP = b.price;
                const aS = a.areaSize;
                const bS = b.areaSize;
                const aR = a.numberOfRooms;
                const bR = b.numberOfRooms;
                const aB = a.numberOfBedrooms;
                const bB = b.numberOfBedrooms;

                /*if(this.userSettings.getAppSetting("filterMinPrice", "number") >= a.price)
                    console.log(a.price + " is smaller than " + this.userSettings.getAppSetting("filterMinPrice", "number"));*/

                const aID = a.ID;
                const bID = b.ID;

                //Price sort (primary)
                const priceSort = this.userSettings.getAppSetting("sortByPrice", "string");
                if(priceSort == "asc") {
                    if (aP > bP) return 1;
                    if (aP < bP) return -1;
                } else if (priceSort == "desc") {
                    if (aP < bP) return 1;
                    if (aP > bP) return -1;
                } else {
                    count++;                    
                }

                //Areasize sort (secondary)
                const sizeSort = this.userSettings.getAppSetting("sortBySize", "string");
                if(sizeSort == "asc") {
                    if (aS > bS) return 1;
                    if (aS < bS) return -1;
                } else if (sizeSort == "desc") {
                    if (aS < bS) return 1;
                    if (aS > bS) return -1;
                } else {
                    count++;
                }

                //Rooms sort (tertiary)
                const roomSort = this.userSettings.getAppSetting("sortByRooms", "string");
                if(roomSort == "asc") {
                    if (aR > bR) return 1;
                    if (aR < bR) return -1;
                } else if (roomSort == "desc") {
                    if (aR < bR) return 1;
                    if (aR > bR) return -1;
                } else {
                    count++;
                }

                //Bedrooms sort (quaternary)
                const bedroomSort = this.userSettings.getAppSetting("sortByBedrooms", "string");
                if(bedroomSort == "asc") {
                    if (aB > bB) return 1;
                    if (aB < bB) return -1;
                } else if (bedroomSort == "desc") {
                    if (aB < bB) return 1;
                    if (aB > bB) return -1;
                } else {
                    count++;
                }

                if(count = 4) {
                    return aID > bID ? 1 : -1;
                }
            })
            return data;
        })
    }
}

The data being retrieved here, looks like this: file.json

[
  {
    "ID": 1,
    "description": "Lorem ipsum dolor sit amet, consectetur adipiscing ...",
    "price": 800.25,
    "agreementType": "unknown",
    "streetName": "street1",
    "houseNumber": 249,
    "postCode": "postcode",
    "place": "New Orlands",
    "status": "status",
    "constructionYear": 1999,
    "areaSize": 5540,
    "numberOfRooms": 545,
    "numberOfBedrooms": 21,
    "garageType": "",
    "garageCapacity": 0
  },
  {
     //...
  }
]

and the property model, which the JSON format "adheres" to, looks as follows...

property.model.ts

export class Property {
    ID: number;
    description: string;
    price: number;
    agreementType: string;
    streetName: string;
    houseNumber: number;
    postCode: string;
    place: string;
    status: string;
    constructionYear: number;
    areaSize: number;
    numberOfRooms: number;
    numberOfBedrooms: number;
    garageType: string;
    garageCapacity: number;
}

I'm displaying my data in the property component simply using an async pipe, which works just fine: *ngFor="let item of propertyData | async". The sorting works as well. It's the filtering I have an issue with.

For now, I'm simply trying to apply a static filter inside the sortAllProperties() method. Making it dynamic and giving it its own class, methods etc can come later.

It's also hard finding the exact right information for this, because most of it is outdated and uses http rather than httpClient, which is of course slighty different.

Every attempt I've made so far (all copied from internet examples and slightly adjusted to fit my use-case) resulted in an error. The closest I got so far is .filter((property) => property.price > 800) which I tried placing in front of, and later after the .map() function, both resulting in the same error:

[ts] Property 'price' does not exist on type 'Property[]'.

Could it be that I'm missing some functions I should use on the observable before filtering? I'm really at a loss right now.

Thank you in advance.


回答1:


With the help of another programmer, I finally managed to get the solution. As usual, it turned out to be pretty simple:

return this.getProperties()
.map(properties => properties.filter(property=> property.price > 810)
.sort((a: Property, b: Property) => {
   //sorting stuff
})

That's for one filter. If you want to apply multiple filters, you could probably do something like

return this.getProperties()
.map(properties => properties.filter((property) => {
   //filter coniditions, arrays etc
   return property;
})
.sort((a: Property, b: Property) => {
   //sorting stuff
})


来源:https://stackoverflow.com/questions/48633254/filtering-an-observable-in-angular-nativescript

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!