I want to filter the results from my store in React-Redux. Therefor I have created a filter selector.
My code only returns all the "shoppers", while it should only be returning the filtered shoppers.
Each shopper has an array of reviews that contains (one or more) objects with the review (text) and review number. We want to filter on the review number. See printscreen:
enter image description here
So to clarify, I want to filter by the reviews of a shopper and if that number >= the filter to then return only the shoppers that match this criteria.
What am I doing wrong here? How can I get it to return only the filtered results?
export const selectShoppersWithFilters = (filters) => (state) => {
let shoppers = [...state.publicShoppers];
if (filters.minAverageReview) {
return shoppers.filter((shopper) => {
return shopper.reviews.map((review) => {
if (review.review >= filters.minAverageReview) {
return (shoppers = shopper);
}
});
});
}
console.log(shoppers);
return shoppers;
};
ps. bear with me, I'm a junior developer...
Assuming you are trying to filter shoppers that have "at least one review higher than minAverageReview" I think a filter function is enough, you don't need map.
return shoppers.filter((shopper) => {
return
shopper.reviews.some((review) => review.review >= filters.minAverageReview)
});
So in the filter function, you pass a callback that checks for each element and decide to filter out that element or not based on your own criteria, the callback function must return a boolean. The element that doesn't satisfy the criteria (callback returns false) will be filtered out. Here my some() checks if the array (shopper.reviews) has at least one review element that has review higher than minAverageReview.
Related
I'm trying to get the temperature of each hour from this website: https://www.smhi.se/vader/prognoser/ortsprognoser/q/Stockholm/2673730
I'm getting the data from https://opendata-download-metfcst.smhi.se/api/category/pmp3g/version/2/geotype/point/lon/16/lat/58/data.json. The "t" object is the temperature.
The problem I have is displaying the data for each hour in the repeater.
Here is my backend-code:
import { getJSON } from 'wix-fetch';
export async function getWeather() {
try {
const response = await getJSON('https://opendata-download-metfcst.smhi.se/api/category/pmp3g/version/2/geotype/point/lon/16/lat/58/data.json');
console.log(response) // all data
const tempData = response.timeSeries[0].parameters[10].values[0];
return tempData // Only returns "t" - temperature
} catch (e) {
return e;
}
}
The backend part works, however the frontend doesn't.
import { getWeather } from 'backend/getSMHI.jsw'
$w.onReady(function () {
(
getWeather().then(weatherInfo => {
$w('#weatherRepeater').onItemReady(($item, itemData, index) => {
if (index > 6) {
$item('#tempText').text = itemData.timeSeries[index].parameters[1].values[0];
} else if (index === 6) {
$item('#tempText').text = itemData.timeSeries[index].parameters[0].values[0];
} else {
$item('#tempText').text = itemData.timeSeries[index].parameters[10].values[0];
} // The parameters number for "t" changes depending on the index
})
$w('#weatherRepeater').data = weatherInfo;
})
)
})
Seems like there are at least a couple of issues here.
First, you are retrieving a single number from the API and trying to put that in a repeater. From the description of what you're trying to do, it would seem that you mean to be retrieving a list of numbers, probably as an array. You probably want to do some filtering and/or mapping on the response data instead of directly accessing a single value.
Second, the data you send to a repeater must be in the proper format. Namely, it must be an array of objects, where each object has a unique _id property value (as a string). You are not doing that here. You are simply assigning it a number.
Third, and this is just an efficiency thing, you don't need to define the onItemReady inside the then(). Not that it will really make much of a difference here.
My issue is that when i call the function getAllFlashCardsFromQuest(), its call all flash cards ever created in all the pages, i wanna only the objects that comes from a specific pathname, or a way to filter the cards array.
async function getCards() {
let cardsValues = await getAllFlashCardsFromQuest() as FlashCard[]
let cardsFiltered = cardsValues.filter(()=>{
return history.location.pathname === 'CriarAlternativaQuest'
})
console.log(cardsFiltered)
setCards(cardsFiltered)
}
the object look like this:
There's not much context with your code, so I can only help so much, but one thing's for sure, and that is history.location.pathname isn't changing and you're comparing it with another constant. So cardsFiltered will be either a list of true or a list of false.
Whenever you're filtering a list, you need to take each item or a property of each item and use that in your comparison.
Ex.
async function getCards() {
let cardsValues = await getAllFlashCardsFromQuest() as FlashCard[]
let cardsFiltered = cardsValues.filter((cardValueItem) => {
return cardValueItem.pathname === 'CriarAlternativaQuest'
})
}
The thing is that you need to figure out what value or property inside of your cardsValues list that you need to compare it with 'CriarAlternativaQuest'
currently I'm trying to filter and search an array in Ionic v5. But I don't know how to combine these two criteria.
I have a page (room-overview), which displays all objects of a room-array. I get these objects from a "data service", which reads a JSON file.
Part of the room-overview.ts-file:
ionViewDidEnter() {
this.setSearchedItems('');
this.searchControl.valueChanges
.pipe(debounceTime(300))
.subscribe(search => {
this.searching = false;
this.setSearchedItems(search);
});
}
onSearchInput() {
this.searching = true;
}
setSearchedItems(searchTerm) {
this.rooms = this.dataService.searchItems(searchTerm);
}
On the room-overview page, there is a search bar, which can be used to search the individual objects. This search bar calls the onSearchInput()-method.
<ion-searchbar [formControl]="searchControl (ionChange)="onSearchInput()">
For that, I have a filter/search-service that gives me all objects which fits the search term. "items" is an array of all room-objects.
searchItems(searchTerm) {
return this.items.filter(item => {
return item.name.toLowerCase().indexOf(searchTerm.toLowerCase()) > -1;
});
}
Besides the search, it should be possible to filter by certain criteria (for example, whether a room is in a certain building or not). This filter possibility is solved via a modal page that passes the values to the room-overview page when it will be closed.
Either the search or the filtering can be done individually, but I do not know how to combine both. I think the "searchItem()"-method should not only filter on the room-object array. It should be able to filter before and use only the filtered array.
I hope someone can help me :-)
Perhaps something like this?
searchAndFilterItems(searchTerm) {
const filteredItems = this.items.filter(item => {
// Apply filters
});
return filteredItems.filter(item => {
return filteredItems.name.toLowerCase().indexOf(searchTerm.toLowerCase()) > -1;
});
}
I am having a really hard time solving this issue I'm currently having. You see, I am using Firebase as my database to store and fetch data.
Right now, I want to be able to return an array that is being made inside a Firebase .once call, but I am having some difficulties. This is my code so far:
Calling the function (a return function):
<p>{this.fetchStartingPrice(singleProduct.id)}</p>
This is where I want to display the specific value, that I am trying to fetch down below:
fetchStartingPrice(category){
let promises = [];
promises.push(this.fetchPrices(category));
Promise.all(promises).then(result => {
console.log(result);
})
}
I have just used a console.log in an attempt to troubleshoot errors.
fetchPrices(category){
var allPrices = [];
allProductsFirebase.child(category).once('value', (snapshot) => {
snapshot.forEach((childSnapshot) => {
if(childSnapshot.key == category){
allPrices.append(childSnapshot.val().brand);
}
});
return allPrices;
})
}
So basically, I want to loop through the allProductsFirebase in an attempt to first identify the brand of the product, and if it matches with the brand that has been used as a parameter in fetchStartingPrice() and fetchPrises(), I want to store the specific price of that product in an array of numbers (prices). After I have looped through the whole snapshot, I want to return the full array containing only product prices, and then through fetchStartingPrice(), I want to use Math.min(promises) to grab the lowest number in that array. However, I am having a really hard time doing this. Could someone please help me with this?
I want to be able to then, after all of this, return the value in fetchStartingPrice().
fetchPrices() must return Promise or be Promise. you are returning nothing from fetchPrices() ( you are returning allPrices in the .once() scope ). try to return the result ( if it returns Promise ) that .once() returns.
fetchPrices(category){
var allPrices = [];
return allProductsFirebase.child(category).once('value', (snapshot) => {
snapshot.forEach((childSnapshot) => {
if(childSnapshot.key == category){
allPrices.append(childSnapshot.val().brand);
}
});
return allPrices;
})
}
In one component I can filter my array using the following:
// Array of product objects
const result = products.filter(p => p.name.includes('val'));
and value of products remains same as the first value but filtered value stores in result.
But in the following code, filter() filters array of strings itself:
// Array of strings
const result = strs.filter(s => s.includes('val'));
The question is how can I filter strings and return result without modifying the strs itself?
Note: I tried with array.filter(function() { return res; }); but didn't make any change.
It returns the filtered ones and don't change the actual array. You are doing something wrong
const strs = ['valval', 'bal', 'gal', 'dalval'];
const result = strs.filter(s => s.includes('val'));
console.log(strs);
console.log(result);
First thing we need to know is, if we filter our list we loose our original data
products: any[] = [
{
"productId": 1,
"productName": "foo-bar",
"price": 32.99
}
]
and can't get it back without re-getting the data from it's source so we have to make another list to store the filtered list.
filteredProduce: any[];
Next if you are working to show a list of filtered product on a grid or something like this we need a way to know when the user changes the filter criteria. we could use event binding and watch for key presses or value changes, but an easier way is to change our _listFilter property into a getter and setter, like this
get listFilter: string {
return this._listFilter;
}
set listFilter(value:string) {
this._listFilter= value;
}
next we want to set our filteredProducts array to the filtered list of products like this
set listFilter(value:string) {
this._listFilter= value;
this.filteredProducts = this._listFilter? this.performFilter(this._listFilter) : this.products;
}
in preceding code we are using js conditional operator to handle the posibility that _listFilterstring is empty, null or undefined.
Next we use this.performFilter(this._listFilter) to filter our list.
performFilter(filterBy: string): any[] {
filterBy = filterBy.toLocaleLowerCase();
return this.products.filter((product: any) =>
product.productName.toLocaleLowerCase().indexOf(filterBy) !== -1);
}
Finally we should assign the main list of products to the filteredProducts and _listFilter to what we want.
constructor() {
this.filteredProducts = this.products;
this._listFilter= 'foo-bar';
}
last step is to change our template to bind to our filteredProducts property.