After working on this for a few days I finally have a working version. The code in the Wix example linked below is right , but it takes a bit of work to make it function. Figuring this out took piecing together info from a lot of googling / youtubing / experimentation and I thought it might be useful to future googlers to write out exactly how I got this working with all the Wix elements and coding involved. I’ll start with two bits of info I was really hung up on:
- Yes, you will need multiple Wix collections for this work! The first is what we’ll call the Main Collection. This is the collection you’ll be searching / filtering through the code and is made up of all your data put into multiple fields. This collection will then be added to your page as ‘dataset1’ (or whatever you choose to name it). In this example, the IDs of the fields of my Main Collection are “tags”, “yearfilmed”, “enlocationname”, “currentstatus”, and “media”.
So what are the other collections and what should they look like? Basically, for every field in your Main Collection you want to be searching / filtering with a dropdown element on the page, you will need a separate Reference Collection. So, in this example, I’ve created “year”, “street”, “status”, and “media” Reference Collections (the “tags” field works differently and does not need a separate collection, I’ll explain more below). Each of these Reference Collections has one field containing data matching its corresponding field in the Main Collection. Let’s take a look at some examples:
Here is my Main Collection with the “tags”, “yearfilmed”, “enlocationname”, “currentstatus”, and “media” fields. (there are other fields here as well, but they are not related to getting the search / filtering to work).
And here is my “year” Reference Collection:
Just one field. You’ll note that the data here doesn’t match exactly. In the Main Collection I used months and years, whereas in this Reference Collection it’s just the years. This works because the code we’ll be using doesn’t need there to be an exact match between the collections, it’s searching for anything in the Main Collection’s “yearfilmed” field that contains the data in the “year” collections one field. So a search for “2017” will return the data labeled both “Summer 2017” and “Sept 2017” from the main collection. A caveat here that I am not a coder at all, but so far to me it seems like using these simplified versions of the data in the reference collections is just as effective as using exact data and prevents you from having massive amounts of duplicates.
One final note about setting up collections before moving on; these reference collections DO NOT have to be on the page as datasets.
- The other very important thing I learned while doing this is that Wix DOES NOT LIKE CUT AND PASTE CODE. When I first tried to get this to work I copied the code from the example page linked below, added in my own collection and element data, and found that it didn’t work at all. It was only when I went in, completely deleted potions of the code, and rewrote it that it started to work for me. Here are the types of lines I needed to write in this way:
Any time you reference an element on your page it helps to completely delete the line from the copied code and write it back in yourself.
Same goes for anywhere in the code that references a string or page element. In these cases, I would delete the () and everything inside, there rewrite it myself. A good sign is if the Wix editor offers to autofill in the element or string you’re typing in.
With those two notes here is my final code for a search bar and four dropdowns. To review the collections, fields, and elements in the order they appear here:
-
“year” = the Reference Collection that has data matching up to the “yearfilmed” field of my Main Collection
-
“street” = the Reference Collection that has data matching up to the “enlocationname” field of my Main Collection
-
“status” = the Reference Collection that has data matching up to the “currentstatus” field of my Main Collection
-
“media” = the Reference Collection that has data matching up to the “yearfilmed” field of my Main Collection
-
“input1” = the page’s search bar
-
“dropdownYear” = A dropdown on the page tied to the “year” Reference Collection
-
“dropdownStreet” = A dropdown on the page tied to the “street” Reference Collection
-
“dropdownStatus” = A dropdown on the page tied to the “status” Reference Collection
-
“dropdownMedia” = A dropdown on the page tied to the “media” Reference Collection
-
“dataset1” = a dataset of my Main Collection
If you feel like you have a grasp on everything so far you can simply copy the code below and replace the collections, fields, and elements with your own and it should work! Remember that Wix doesn’t like copy/paste and you may need to delete and rewrite the code around your elements.
import wixData from "wix-data";
$w.onReady(() => {
loadyear();
loadstreet();
loadstatus();
loadmedia();
});
let lastFilterSearch;
let SearchBar;
let searchWords;
let lastFilterYear;
let lastFilterStreet;
let lastFilterStatus;
let lastFilterMedia;
let debounceTimer;
//search bar//
export function input1_keyPress(event, $w) {
if (debounceTimer) {
clearTimeout(debounceTimer);
debounceTimer = undefined;
}
debounceTimer = setTimeout(() => {
SearchBar = $w('#input1').value;
searchWords = SearchBar.split(" ");
filter(searchWords, lastFilterYear, lastFilterStreet, lastFilterStatus, lastFilterMedia);
}, 500);
}
//dropdown search//
export function dropdownYear_change(event) {
filter(searchWords, $w('#dropdownYear').value, lastFilterStreet, lastFilterStatus, lastFilterMedia);
}
export function dropdownStreet_change(event, $w) {
filter(searchWords, lastFilterYear, $w('#dropdownStreet').value, lastFilterStatus, lastFilterMedia);
}
export function dropdownStatus_change(event, $w) {
filter(searchWords, lastFilterYear, lastFilterStreet, $w('#dropdownStatus').value, lastFilterMedia);
}
export function dropdownMedia_change(event, $w) {
filter(searchWords, lastFilterYear, lastFilterStreet, lastFilterStatus, $w('#dropdownMedia').value);
}
//combined filter//
function filter(wordArray, Year, Street, Status, Media) {
if (lastFilterSearch !== wordArray || lastFilterYear !== Year || lastFilterStreet !== Street || lastFilterStatus !== Status || lastFilterMedia !== Media)
{ let newFilter = wixData.filter()
if (wordArray)
for (let i=0; i < wordArray.length; i++)
newFilter = newFilter.contains('tags', wordArray[i]);
if (Year)
newFilter = newFilter.contains('yearfilmed', Year);
if (Street)
newFilter = newFilter.contains('enlocationname', Street)
if (Status)
newFilter = newFilter.contains('currentstatus', Status)
if (Media)
newFilter = newFilter.contains('media', Media)
$w('#dataset1').setFilter(newFilter);
lastFilterSearch = wordArray;
lastFilterYear = Year;
lastFilterStreet = Street;
lastFilterStatus = Status;
lastFilterMedia = Media;
}
}
//loading dropdown filters//
function loadyear() {
wixData.query('year')
.find()
.then(res => {
let options = [{"value": '', "label": 'All Years'}];
options.push(...res.items.map(year => {
return {"value": year.title, "label": year.title};
}));
$w('#dropdownYear').options = options;
});
}
function loadstreet() {
wixData.query('street')
.find()
.then(res => {
let options = [{"value": '', "label": 'All Streets'}];
options.push(...res.items.map(street => {
return {"value": street.title, "label": street.title};
}));
$w('#dropdownStreet').options = options;
});
}
function loadstatus() {
wixData.query('status')
.find()
.then(res => {
let options = [{"value": '', "label": 'All Statuses'}];
options.push(...res.items.map(stat => {
return {"value": stat.title, "label": stat.title};
}));
$w('#dropdownStatus').options = options;
});
}
function loadmedia() {
wixData.query('media')
.find()
.then(res => {
let options = [{"value": '', "label": 'All Media'}];
options.push(...res.items.map(media => {
return {"value": media.title, "label": media.title};
}));
$w('#dropdownMedia').options = options;
});
}
If you’re still not having luck or wonder how this code works I’ll do my best here to break it down a little and show which bits you need to change (though again I’m not a coder and am doing a lot of intuiting here, I’m sure a pro coder would be laughing at me )
import wixData from "wix-data";
$w.onReady(() => {
loadyear();
loadstreet();
loadstatus();
loadmedia();
});
This bit ties to your Reference Collections and will be used later in the code to define your dropdown elements. Change these so they read “loadyourreferencecollectionname();”
If you have fewer dropdowns, delete one of the “loadX();” lines. If you have more, add another “loadyourreferencecollectionname();”
let lastFilterSearch;
let SearchBar;
let searchWords;
let lastFilterYear;
let lastFilterStreet;
let lastFilterStatus;
let lastFilterMedia;
let debounceTimer;
This bit is defining the strings you’ll be using in the rest of the code. I’ve changed them in my code to match up with my collections and fields as a way of keeping internal consistency.
If you have fewer dropdowns, delete one of the “let lastFilterX;” lines. If you have more, add another “let lastFilterX;”
export function input1_keyPress(event, $w) {
if (debounceTimer) {
clearTimeout(debounceTimer);
debounceTimer = undefined;
}
debounceTimer = setTimeout(() => {
SearchBar = $w('#input1').value;
searchWords = SearchBar.split(" ");
filter(searchWords, lastFilterYear, lastFilterStreet, lastFilterStatus, lastFilterMedia);
}, 500);
}
This bit is the search bar. I’ve changed it a bit from the one in the example linked below so that it searches for each word in the search bar regardless of order; ie “Animals cats dogs” produces the same result as “cats Animals dogs”. "Make sure the place where it says ‘input1’ matches the ID of your search bar.
//dropdown search//
export function dropdownYear_change(event, $w) {
filter(searchWords, $w('#dropdownYear').value, lastFilterStreet, lastFilterStatus, lastFilterMedia);
}
export function dropdownStreet_change(event, $w) {
filter(searchWords, lastFilterYear, $w('#dropdownStreet').value, lastFilterStatus, lastFilterMedia);
}
export function dropdownStatus_change(event, $w) {
filter(searchWords, lastFilterYear, lastFilterStreet, $w('#dropdownStatus').value, lastFilterMedia);
}
export function dropdownMedia_change(event, $w) {
filter(searchWords, lastFilterYear, lastFilterStreet, lastFilterStatus, $w('#dropdownMedia').value);
These bits are the search functionality of the dropdowns. In this line:
export function dropdownYear_change(event, $w)
make sure you’ve changed it to YourDropdownID_change
Its also important to maintain consistency between each dropdown here:
filter(searchWords, lastFilterYear, $w('#dropdownStreet').value, lastFilterStatus, lastFilterMedia)
ie, “searchWords” should always be first, “lastFilterYear” second, and so on, while replacing the string for the current dropdown you’re coding to “$w(‘#YourDropdownID’).value”, but keeping it in the same place in the order.
If you have fewer dropdowns, delete the entirety of one of the 'export function’s. If you have more, add another ‘export function’ AND add in the corresponding ‘lastFilterX’ into the same place in the order in all of the previous dropdowns.
//combined filter//
function filter(wordArray, Year, Street, Status, Media) {
if (lastFilterSearch !== wordArray || lastFilterYear !== Year || lastFilterStreet !== Street || lastFilterStatus !== Status || lastFilterMedia !== Media)
{ let newFilter = wixData.filter()
if (wordArray)
for (let i=0; i < wordArray.length; i++)
newFilter = newFilter.contains('tags', wordArray[i]);
if (Year)
newFilter = newFilter.contains('yearfilmed', Year);
if (Street)
newFilter = newFilter.contains('enlocationname', Street)
if (Status)
newFilter = newFilter.contains('currentstatus', Status)
if (Media)
newFilter = newFilter.contains('media', Media)
$w('#dataset1').setFilter(newFilter);
lastFilterSearch = wordArray;
lastFilterYear = Year;
lastFilterStreet = Street;
lastFilterStatus = Status;
lastFilterMedia = Media;
}
}
So this is where again I have to say NOT A CODER . I don’t really know how this bit works, just that it does. MY GUESS is that you’re redefining the last user input from each dropdown and search bar (lastFilterYear becomes Year) and then cross-referencing all of those user inputs against each other to produce a final search result on the page.
As long as you maintain internal consistency you can change the wording to anything you’d like; ie “lastFilterYear !== Year” could be “lastFilterProduct !==Product” if that suits your page/project better. Just make sure you’re using that same phrasing through the whole code; if you’re using ‘lastFilterProduct’ instead of ‘lastFilterYear’ make sure all instances of 'lastFilterYear in the entire code are replaced with ‘lastFilterProduct’. This goes for any other change you make as well.
If you have fewer dropdowns, delete one of the “lastFilterX !== X” lines, one of the “if (X) newFilter = newFilter.contains(‘X’, X);” lines, and one of the “lastFilterX = X;” lines. If you have more, add another “lastFilterX !== X” in the top brackets, add an “if (X) newFilter = newFilter.contains(‘X’, X);” into the set of ‘if’ statements, and add an lastFilterX = X;" at the bottom.
Final things for this bit; change these lines to match the fields in your Main Collection:
if (Year)
newFilter = newFilter.contains('yearfilmed', Year);
In this line ‘yearfilmed’ should be changed to whatever the ID of the field in the Main Collection you want to be cross referencing with the “year” Reference Collection.
Also change this to match whatever the name of the dataset on your page is:
$w('#dataset1').setFilter(newFilter);
LAST BITS!
//loading dropdown filters//
function loadyear() {
wixData.query('year')
.find()
.then(res => {
let options = [{"value": '', "label": 'All Years'}];
options.push(...res.items.map(year => {
return {"value": year.title, "label": year.title};
}));
$w('#dropdownYear').options = options;
});
}
Remember that bit way back at the beginning? These tie back to those! Each one of these is looking at a Reference Collection and uses its one field to define the options of a dropdown on the page. In addition, its adding an option (above its ‘All Years’, change to whatever you’d like) that will reset the filter if selected.
If you have fewer dropdowns delete the entirety of one of these functions. If you have more dropdowns add in a new function as follows:
function loadX() {
wixData.query('X')
.find()
.then(res => {
let options = [{"value": '', "label": 'All X'}];
options.push(...res.items.map(year => {
return {"value": year.title, "label": year.title};
}));
$w('#dropdownX').options = options;
});
}
I think thats everything! All I need to figure out now is how to make a reset button that actually resets the search bar haha. Hope this helps someone out there! I’ll update it if I get a working button or if I think of a better way to phrase anything here!