问题
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