Issues with Filtering

Hi, I am having issues with my filter code. I basically wish to filter my repeaters by Type (hotel, house, ALL, etc), Guests, Bedrooms and Bathrooms. The last 3 have to display matches that are equal or more than, and the Type has to match House, Hotel (from database) or ‘ALL’ which lists all. In testing it seems like the Type dropdown is not working correctly.

MY SITE: http://tailoredwebdesign.wixsite.com/book-the-best/queensland1

The code does filter, but has errors:

  1. If you select guests 3, it does filter out to have properties showing with 3 or more, but if you then pick 2 bedrooms, it filters out all the ones with less than 2 BUT DOESN’T remember the guests selection.


MY FULL CODE:

import wixData from ‘wix-data’;
let originalPropertiesInfo = ;
let filteredResults = ;
$w.onReady(function () {
//Query to get the information from the database
wixData.query(“Properties”)
.find()
.then((results) => {
originalPropertiesInfo = results.items;
$w(#repeater2).data = originalPropertiesInfo;
})
.catch((err) => {
let errorMsg = err;
});
//Set the information to the repeater
$w(#repeater2).onItemReady(($w, itemData) => {
//add here all the relevant elements of the repeater
//In this case, I’ve added a text and an image to the repeater
$w(#text52).text = itemData.title;
$w(‘#image2’).src = itemData.images;
$w(#text53).text = itemData.guests;
$w(#text50).text = itemData.bedrooms;
$w(#text51).text = itemData.bathrooms;
});
});

function filterResults() {
filteredResults = ;
const type = $w(‘#Type’).value;
const guests = $w(‘#Guests’).value;
const rooms = $w(‘#Rooms’).value;
const bathrooms = $w(‘#Bathrooms’).value;

if (type && type !== 'Choose type of accommodation') { 
	filteredResults = originalPropertiesInfo.filter(item => item.type === type); 
}  

if (guests && guests !== 'Choose number of guests') { 
	filteredResults = originalPropertiesInfo.filter(item => item.guests >= guests); 
} 
//after the first if statement, the results is filtered by state 

if (rooms && rooms !== 'Choose number of beds') { 
	filteredResults = originalPropertiesInfo.filter(item => item.bedrooms >= rooms); 
} 

if (bathrooms && bathrooms !== 'Choose number of bathrooms') { 
	filteredResults = originalPropertiesInfo.filter(item => item.bathrooms >= bathrooms); 
} 
//results is filtered by both guests and rooms  
Guests_change(); 

}

export function Guests_change(event) {
//filtering the results
//setting the data
$w(‘#repeater2’).data = filteredResults;
//setting the repeater elements
$w(‘#repeater2’).forEachItem(($w, itemData, index) => {

	$w(`#text52`).text = itemData.title; 
	$w('#image2').src = itemData.images; 
	$w(`#text53`).text = itemData.guests; 
	$w(`#text50`).text = itemData.bedrooms; 
	$w(`#text51`).text = itemData.bathrooms; 
}); 

}

export function refine_onClick(event, $w) {
filterResults();
$w(“#button6”).show();
}

export function button6_onClick(event, $w) {
$w(“#Type”).selectedIndex = 0;
$w(“#Guests”).selectedIndex = 0;
$w(“#Rooms”).selectedIndex = 0;
$w(“#Bathrooms”).selectedIndex = 0;
$w(“#button6”).hide();
filterResults();

}

Thanks a lot, I really need to get this sorted!

Sam are you around?

Indeed, I am around.

I’ve taken a quick look and it looks like you have a logical error in your filtering code. (BTW I see you are filtering using JavaScript instead of filtering on a dataset, which would have been my first suggestion.)

Anyhow, you overwrite your filter when you filter based on more than one value. Each time you are resetting filteredResults based on filtering the originalPropertiesInfo. Instead, in your filterResults function, I think you should begin by copying the originalPropertiesInfo into filteredResults. Then only use the filtered results from there.

Something like this:

function filterResults() {
	filteredResults = [];
	const type = $w('#Type').value;
	const guests = $w('#Guests').value;
	const rooms = $w('#Rooms').value;
	const bathrooms = $w('#Bathrooms').value;
	
	filteredResults = originalPropertiesInfo.slice();

        if (type && type !== 'Choose type of accommodation') {
		filteredResults = filteredResults.filter(item => item.type === type);
	} 
	
	if (guests && guests !== 'Choose number of guests') {
		filteredResults = filteredResults.filter(item => item.guests >= guests);
	}
	
	if (rooms && rooms !== 'Choose number of beds') {
		filteredResults = filteredResults.filter(item => item.bedrooms >= rooms);
	}
	
	if (bathrooms && bathrooms !== 'Choose number of bathrooms') {
		filteredResults = filteredResults.filter(item => item.bathrooms >= bathrooms);
	}
	
	Guests_change();
}

Thank you Sam that mostly works.
My code (also has reset button):

import wixData from ‘wix-data’;
let originalPropertiesInfo = [];
let filteredResults = [];
$w.onReady(function () {
//Query to get the information from the database
wixData.query(“Properties”)
.find()
.then((results) => {
originalPropertiesInfo = results.items;
$w(#repeater2).data = originalPropertiesInfo;
})
.catch((err) => {
let errorMsg = err;
});
//Set the information to the repeater
$w(#repeater2).onItemReady(($w, itemData) => {
//add here all the relevant elements of the repeater
//In this case, I’ve added a text and an image to the repeater
$w(#text52).text = itemData.title;
$w(‘#image2’).src = itemData.images;
$w(#text53).text = itemData.guests;
$w(#text50).text = itemData.bedrooms;
$w(#text51).text = itemData.bathrooms;
});
});

function filterResults() {
filteredResults = [];
const type = $w(‘#Type’).value;
const guests = $w(‘#Guests’).value;
const rooms = $w(‘#Rooms’).value;
const bathrooms = $w(‘#Bathrooms’).value;

filteredResults = originalPropertiesInfo.slice(); 

    if (type && type !== 'Choose type of accommodation') { 
	filteredResults = filteredResults.filter(item => item.type === type); 
}  

if (guests && guests !== 'Choose number of guests') { 
	filteredResults = filteredResults.filter(item => item.guests >= guests); 
} 

if (rooms && rooms !== 'Choose number of beds') { 
	filteredResults = filteredResults.filter(item => item.bedrooms >= rooms); 
} 

if (bathrooms && bathrooms !== 'Choose number of bathrooms') { 
	filteredResults = filteredResults.filter(item => item.bathrooms >= bathrooms); 
} 

Guests_change(); 

}

export function Guests_change(event) {
//filtering the results
//setting the data
$w(‘#repeater2’).data = filteredResults;
//setting the repeater elements
$w(‘#repeater2’).forEachItem(($w, itemData, index) => {

	$w(`#text52`).text = itemData.title; 
	$w('#image2').src = itemData.images; 
	$w(`#text53`).text = itemData.guests; 
	$w(`#text50`).text = itemData.bedrooms; 
	$w(`#text51`).text = itemData.bathrooms; 
}); 

}

export function refine_onClick(event, $w) {
filterResults();
$w(“#button6”).show();
}

export function button6_onClick(event, $w) {
$w(“#Type”).selectedIndex = “All”;
$w(“#Guests”).selectedIndex = 0;
$w(“#Rooms”).selectedIndex = 0;
$w(“#Bathrooms”).selectedIndex = 0;
$w(“#button6”).hide();
filterResults();
}

Sam, I do still have some issues though

  1. I have found if the data has a number 10 or above it doesn’t recognize and the filters miss it??
  2. SOLVED
  3. I still want an ‘ALL’ type which lists all the properties without having to add this to the database. Is that possible? It works as it is as a hack, but does give an error of course in the console
  4. I wish to display text for when there are no results. Would it be something like:

export function button6_onClick(event, $w) {
$w(“#Type”).selectedIndex = “All”;
$w(“#Guests”).selectedIndex = 0;
$w(“#Rooms”).selectedIndex = 0;
$w(“#Bathrooms”).selectedIndex = 0;
$w(“#button6”).hide();
filterResults();
if (filterResults()===0)
{$w(“#text55”).show;}
}

  1. I would prefer to do filtering on dataset but was advised against it?
    How would it work, something like this?

import wixData from ‘wix-data’;
$w.onReady( function () {
$w(‘#repeater2’).onItemReady( ($w, itemData) => {
$w(“#text50”).text = itemData.bedrooms;
$w(“#text51”).text = itemData.bathrooms;
$w(“#text53”).text = itemData.people;
$w(“#image2”).src = itemData.images;
} );
} );

$w.onReady( function () {
$w(“#dataset1”).setFilter( wixData.filter()
.ge(‘people’, $w(‘#Guests’).value)
.contains(‘type’, $w(‘#Type’).value)
.ge(‘bedrooms’, $w(‘#Rooms’).value)
.ge(‘bathrooms’, $w(‘#Bathrooms’).value)
)
.then( () => {
console.log(“Dataset is now filtered”);
} )
.catch( (err) => {
console.log(err);
} );
} );

export function refine_onClick(event, $w) {
$w(“#button6”).show();
wixData.query(‘Queensland’)
.ge(‘people’, $w(‘#Guests’).value)
.contains(‘type’, $w(‘#Type’).value)
.ge(‘bedrooms’, $w(‘#Rooms’).value)
.ge(‘bathrooms’, $w(‘#Bathrooms’).value)
.find()
.then(res => {
$w(‘#repeater2’).data = res.items;
});
}

export function button6_onClick(event, $w) {
$w(“#dataset1”).setFilter( wixData.filter() );
$w(“#Type”).selectedIndex = “ALL”;
$w(“#Guests”).selectedIndex = 0;
$w(“#Rooms”).selectedIndex = 0;
$w(“#Bathrooms”).selectedIndex = 0;
$w(“#button6”).hide();
}

http://tailoredwebdesign.wixsite.com/book-the-best/queensland1

THANK YOU!!!

Hey again,

  1. I’m not sure what you mean here
  2. Great
  3. An “all” is the same as not filtering. So just check if the value is “all”, and if it is, skip that filter.
  4. fitleredResults is an array so you can check it’s length property to see if it is empty.
  5. That is the general idea.
  1. If there is 10 (guests,bathrooms etc) in my database then the filter doesn’t seem to work? Is this a bug?

  2. Ok so

if ($w (‘#Type’).value !== ‘All’) {dont filterResults??}

  1. if (filteredResults () = 0){
    $w (‘#box5’).show;}

???

Thanks for your patience

  1. I think I get what you’re saying. Did you by any change make the field that holds the 10 a text field instead of a number field?
  2. Sort of the opposite. You wrote if it doesn’t equal all, then filter the results. Anyhow, you should just be incorporating the check into your existing ifs that determine whether a given is run.

ok so I have changed to numbers. what is the syntax for numbers?

$w(#text53).number??

Sorry, if I was not clear. What type is the field in your collection ? If the query is getting a text version of “10” because the field in the collection is the wrong type then your filter will do a textual comparison (where 10 is “less than” 2).

If the problem is your collection field types and you fix them, then in setting the text fields you might need to do:

$w("#textWhatever").text = parseInt(itemData.whatever);

yes that is the issue thank you. They were all text not numbers. I have changed them now.
So parseint is the correct syntax for number types?
it says missing radix parameter? Should it be parseFloat?

Giving me this error too: Wix code SDK error: The text parameter that is passed to the text method cannot be set to the value 9. It must be of type string.

parseInt is the standard JavaScript function for changing a number to a string.

Ok, but it doesn’t work properly at all now. My connected elements on the screen just display their placeholder numbers, not from the collection as before. Coud you please take a look at my site? http://tailoredwebdesign.wixsite.com/book-the-best/queensland

CODE:

import wixData from ‘wix-data’;
let originalPropertiesInfo = [];
let filteredResults = [];
$w.onReady(function () {
//Query to get the information from the database
wixData.query(“Properties”)
.find()
.then((results) => {
originalPropertiesInfo = results.items;
$w(#repeater2).data = originalPropertiesInfo;
})
.catch((err) => {
let errorMsg = err;
});
//Set the information to the repeater
$w(#repeater2).onItemReady(($w, itemData) => {
//add here all the relevant elements of the repeater
//In this case, I’ve added a text and an image to the repeater
$w(#text52).text = itemData.title;
$w(‘#image2’).src = itemData.images;
$w(#text53).text = parseInt(itemData.guests);
$w(“#text50”).text = parseInt(itemData.bedrooms);
$w(“#text51”).text = parseInt(itemData.bathrooms);
});
});

function filterResults() {
filteredResults = [];
const type = $w(‘#Type’).value;
const guests = $w(‘#Guests’).value;
const rooms = $w(‘#Rooms’).value;
const bathrooms = $w(‘#Bathrooms’).value;

filteredResults = originalPropertiesInfo.slice(); 

    if (type && type !== 'Choose type of accommodation') { 
	filteredResults = filteredResults.filter(item => item.type === type); 
}  

if (guests && guests !== 'Choose number of guests') { 
	filteredResults = filteredResults.filter(item => item.guests >= guests); 
} 

if (rooms && rooms !== 'Choose number of beds') { 
	filteredResults = filteredResults.filter(item => item.bedrooms >= rooms); 
} 

if (bathrooms && bathrooms !== 'Choose number of bathrooms') { 
	filteredResults = filteredResults.filter(item => item.bathrooms >= bathrooms); 
} 

Guests_change(); 

}

export function Guests_change(event) {
//filtering the results
//setting the data
$w(‘#repeater2’).data = filteredResults;
//setting the repeater elements
$w(‘#repeater2’).forEachItem(($w, itemData) => {

	$w(`#text52`).text = itemData.title; 
	$w('#image2').src = itemData.images; 
	$w(`#text53`).text = parseInt(itemData.guests); 
	$w("#text50").text = parseInt(itemData.bedrooms); 
	$w("#text51").text = parseInt(itemData.bathrooms); 
}); 

}

export function refine_onClick(event, $w) {
filterResults();
$w(“#button6”).show();
}

export function button6_onClick(event, $w) {
$w(“#Type”).selectedIndex = “ALL”;
$w(“#Guests”).selectedIndex = 0;
$w(“#Rooms”).selectedIndex = 0;
$w(“#Bathrooms”).selectedIndex = 0;
$w(“#button6”).hide();
filterResults();
}

Hi,

Would it be possible for you to share the full code?

Thanks,
Benny

Hi Sam,

Can you please… please… help me as well.

  1. I created a collection, import all my products to the collection via CSV,
  2. Add a gallery to a page
  3. Connected the dataset to my collection
  4. Connected the Gallery to dataset
  5. I managed to create categories as well (for example, dresses, blouses)

But I am unable to add a “Sort” option above the Gallery.
All I need is to add “Price Low | High” as shown on the image.


would really like to add Sort button so my customers would be able to click on to sort the list.
I have no knowledge of coding. can you please provide me with a code and can you please explain to me where to add the code as well.

I am desperate to get a positive answer

Hi, I’ve got a similar question to the original poster. I currently have a drop down filter and a search box filter set up on my dynamic page. Additionally, I have added a dynamic dataset filter to only show dataset entries that contain “Available” in the “Sales status” column (field: ‘salesStatus’). This is because I only want available items to be shown in the dynamic page.

The page seems ok to begin with. However, the issue I have is when I start selecting from the drop down including “All States”, the dynamic page will show all items in my dataset, regardless of that filter for “Sales status”. Is there a way to incorporate that filter into my page so it will NEVER show items that are not available?

Here’s the code from that page:

import wixData from “wix-data”;

$w.onReady(() => {
loadStates();
});

let lastFilterPlate;
let lastFilterState;
let debounceTimer;
export function iPlate_keyPress(event, $w) {
if (debounceTimer) {
clearTimeout(debounceTimer);
debounceTimer = undefined;
}
debounceTimer = setTimeout(() => {
filter($w(‘#iPlate’).value, lastFilterPlate);
}, 500);
}

export function iState_change(event, $w) {
filter(lastFilterPlate, $w(‘#iState’).value);
}

function filter(Plate, State) {
if (lastFilterPlate !== Plate || lastFilterState !== State) {
let newFilter = wixData.filter();
if (Plate)
newFilter = newFilter.contains(‘licencePlateNumber’, Plate);
if (State)
newFilter = newFilter.contains(‘state’, State);
$w(‘#dynamicDataset’).setFilter(newFilter);
lastFilterPlate = Plate;
lastFilterState = State;
}
}

function loadStates() {
wixData.query(‘States’)
.find()
.then(res => {
let options = [{“value”: ‘’, “label”: ‘All States’}];
options.push(…res.items.map(title => {
return {“value”: title.stateAbbreviation, “label”: title.stateAbbreviation};
}));
$w(‘#iState’).options = options;
});

}

Thanks so much for your help!