Connect repeater to filter, please help with code

My website is Stylesweetsmile.com
Under each tab of the menu ( for example dresses) I have added a repeater and connected it to the relevant collection. I am looking for a way to add dropdown and connect the dropdown to the repeater. ( so it will be filtered)

Names of the two dropdowns
Retailer
Brand

When a customer clicks on the retailer dropdown the second dropdown will need to show the brands relevant to that perticular retailer and the repeater will change accordingly.

I have watched videos, read examples on your forum posts related to what I’m trying to do and managed to come up with this code. But I do not know how to connect the code to a repeater. This took me many weeks. I have no knowledge of coding.

Can someone please look at the code below and help me with writing the code to connect the filters with the repeater.

dataset Id: dataset1
Collection Name: dresses2
Retailer Field Key: retailer
Brabd Field key: brand

Thank you for your time.

1 Like

$w.onReady(function () {
uniqueDropDown1();
});

function uniqueDropDown1 (){
wixData.query(“dresses2”)
.limit(1000)
.find()
.then(results => {
const uniqueTitles = getUniqueTitles(results.items);
$w(“#dropdown1”).options = buildOptions(uniqueTitles);
});
function getUniqueTitles(items) {
const titlesOnly = items.map(item => item. retailer);
return […new Set(titlesOnly)];
}
function buildOptions(uniqueList) {
return uniqueList.map(curr => {
return {label:curr, value:curr};
});
}
}
export function genre_change(event, $w) {
uniqueDropDown2();
$w(“#dropdown2”).enable();
}
function uniqueDropDown2 (){
wixData.query(“dresses2”)
.contains(“retailer”, $w(“#dropdown1”).value)
.limit(1000)
.find()
.then(results => {
const uniqueTitles = getUniqueTitles(results.items);
$w(“#dropdown2”).options = buildOptions(uniqueTitles);
});
function getUniqueTitles(items) {
const titlesOnly = items.map(item => item. brand);
return […new Set(titlesOnly)];
}
function buildOptions(uniqueList) {
return uniqueList.map(curr => {
return {label:curr, value:curr};
});
}
}

Hello,

this can be solved with session or local storage.

The basic idea is that on click in the menu you set a local/session item for the brand/retailer that was clicked and go to the dresses page as normal.

Then in the dresses page with the repeater, we read the session/local storage item, (let us assume it is
the brand ‘ASOS’) and we set a filter on the dataset to only get those items from the collection.

To do this you would have to either find a way to set a session/local storage item on menu item click or create a new menu with same design but not one that is pre built, you have to build this one from scratch which will allow you to customize it and modify it as you want. I would suggest trying $w('#menuId).children to try and find which menu item was clicked (so that you can put what was clicked as a session item to be used to filter later)

It would look something like this:


//Menu code:
import {session} from 'wix-storage';

$('#menuId').onClick(event, $w){
     session.setItem('category': event.target.value)
}





//Repeater Page Code:

$w.onReady() {
  const toFilter = session.getItem('category');

$w('#dresses2').setFilter('Brand', toFilter)
}

Hello Majd,

Thank you very much for taking time to reply. I had a look at sessions, but looks like its going to be very difficult for me to create the code. My knowledge is zero with codes. I watched a video and only filled in the blanks to create the code above.

Thank you again for your help.

No worries! It is never to late to start coding :). Any trouble you have you can post here, and I’m sure a Moderator will get to it.

Another option is to hire a wix expert here: https://www.wix.com/arena/web-designers/1

Best of luck!
Majd

Hello Dilly :slight_smile:

I received your chat message. So you want to filter a repeater based on 2 dropdown selections. I do not have a tutorial video on this just yet, but here is the tutorial site that should give you some idea on how to accomplish this: https://codequeen.wixsite.com/multi-search

I am also available for private tutoring if needed.

Hello Nayeli,
Thank you very much for taking time to reply. I had a look at the link you have provided but for someone like me it is very difficult understand which part of the code to use. I spend all day going through the messages in this forum to find out if there is a code that I could use.

I think using two filters are complicated, so Now I have decided to use ONE filter. I found a code on this message https://www.wix.com/code/home/forum/community-discussion/filtering-repeater
I added the code to onclick

import wixData from ‘wix-data’;
$w.onReady(function () {

$w(" #filterButton “).onClick(() => { $w(” #dataset2 ").setFilter(wixData.filter()

.eq(“type”, $w(" #userInputDropdownBox ").value)); });

});

But when I click on Brand button there are few problems

  1. Duplicate brand names
  2. After i click a brand( for example Chi Chi London), the repeater will show the dresses relevant to that brand, but as you see on image two when I click on the button I can only see Chi Chi London.

I do not have a clue how to fix this. Can you kindly help me with the correct code. I appreciate it very much.

Hi Dilly,
Can you please share a link to your site and specify the name of the page so we can inspect?
Roi.

@roi-bendet Hello Roi,

The link is https://www.stylesweetsmile.com/dress
I found another code to delete duplicates. so I filled in the blanks and pasted it to OnClick as well. Now it appears that there are no duplicates. But still you will see when you click on a brand name for example Ted baker the repeater will change, but under the brand tab it will only show the name Ted Baker not all the brands

Roi, I have copied and pasted these codes, not knowing whether I am doing it correctly.

I would be extremely grateful if you could type the correct complete code below, so that I can copy and paste it on my website.
Please indicate the correct Event i need to paste the code to. (onClick…)

Is there a way to show all the brands in alphabetical order please (A-Z)

I look forward to your kind reply. Thank you very much for your help.

@dilly Hi Dilly: I was just finishing a mini tutorial on this for you when the browser crashed and I lost the post. BUT I did keep the code I created :-).

OK There are many things that you need to consider to get the effect that you want. What I have done is to take your original question and answer that.

Here is the resulting code that I’ll explain below…

$w.onReady(function () {
    uniqueDropDown1();
    uniqueDropDown2();
    $w('#dropdown1').onChange(dropdownHasChanged);     
    $w('#dropdown2').onChange(dropdownHasChanged);
 $w('#resetDropdownsButton').onClick(resetDropdownsButton_clicked);
}
 
function resetDropdownsButton_clicked(event) {
    $w('#dropdown1').selectedIndex = undefined;
    $w('#dropdown2').selectedIndex = undefined;
    dropdownHasChanged(); 
}
​
function uniqueDropDown1 (){
    wixData.query("dresses2")
        .limit(1000)
        .find()
        .then(results => {
            const uniqueTitles = getUniqueTitles(results.items, 'retailer');
            $w("#dropdown1").options = buildOptions(uniqueTitles);
        });
    }
}

export function genre_change(event, $w) {
    uniqueDropDown2("retailer");
    $w("#dropdown2").enable();
}

function uniqueDropDown2 (filter) {
    let query = wixData.query("dresses2");
    if (filter) {
        query = query.contains(filter, $w("#dropdown1").value);
    }
 
    query.limit(1000)
        .find()
        .then(results => {
            const uniqueTitles = getUniqueTitles(results.items, 'brand');
            $w("#dropdown2").options = buildOptions(uniqueTitles);
        });
}

function getUniqueTitles(items, columnKey) {
    const titlesOnly = items.map(item => item[columnKey]);
    return [...new Set(titlesOnly)];
}

function buildOptions(uniqueList) {
    return uniqueList.map(curr => {
        return {label:curr, value:curr};
    });
}

function dropdownHasChanged(event) {
    let retailer = getRetailerDropDown();
    let brand = getBrandDropDown();
    let datasetFilter = wixData.filter(); // Empty filter
 
    if (retailer) {
        datasetFilter = datasetFilter.eq('retailer', retailer);
    }
 
    if (brand) {
        datasetFilter = datasetFilter.eq('brand', brand);
    }
 
    $w('#dataset2').setFilter(datasetFilter);
}

function getBrandDropDown() {
    let result = null;
    // If there is a drop down selected the selectedIndex will be
    // greater than or equal to 0
    if ($w("#dropdown2").selectedIndex >= 0) {
        result = $w("#dropdown2").value;
    }
    return result;
}

function getRetailerDropDown() {
    let result = null;
    // If there is a drop down selected the selectedIndex will be
    // greater than or equal to 0
    if ($w("#dropdown1").selectedIndex >= 0) {
        result = $w("#dropdown1").value;
    }
    return result;
}

@dilly Hi Dilly: I was just finishing a mini tutorial on this for you when the browser crashed and I lost the post. BUT I did keep the code I created :-).

OK There are many things that you need to consider to get the effect that you want. What I have done is to take your original question and answer that.

Here is the resulting code that I’ll explain below…

$w.onReady(function () {
    uniqueDropDown1();
    uniqueDropDown2();
    $w('#dropdown1').onChange(dropdownHasChanged);     
    $w('#dropdown2').onChange(dropdownHasChanged);
 $w('#resetDropdownsButton').onClick(resetDropdownsButton_clicked);
}
 
function resetDropdownsButton_clicked(event) {
    $w('#dropdown1').selectedIndex = undefined;
    $w('#dropdown2').selectedIndex = undefined;
    dropdownHasChanged(); 
}
​
function uniqueDropDown1 (){
    wixData.query("dresses2")
        .limit(1000)
        .find()
        .then(results => {
            const uniqueTitles = getUniqueTitles(results.items, 'retailer');
            $w("#dropdown1").options = buildOptions(uniqueTitles);
        });
    }
}

export function genre_change(event, $w) {
    uniqueDropDown2("retailer");
    $w("#dropdown2").enable();
}

function uniqueDropDown2 (filter) {
    let query = wixData.query("dresses2");
    if (filter) {
        query = query.contains(filter, $w("#dropdown1").value);
    }
 
    query.limit(1000)
        .find()
        .then(results => {
            const uniqueTitles = getUniqueTitles(results.items, 'brand');
            $w("#dropdown2").options = buildOptions(uniqueTitles);
        });
}

function getUniqueTitles(items, columnKey) {
    const titlesOnly = items.map(item => item[columnKey]);
    return [...new Set(titlesOnly)];
}

function buildOptions(uniqueList) {
    return uniqueList.map(curr => {
        return {label:curr, value:curr};
    });
}

function dropdownHasChanged(event) {
    let retailer = getRetailerDropDown();
    let brand = getBrandDropDown();
    let datasetFilter = wixData.filter(); // Empty filter
 
    if (retailer) {
        datasetFilter = datasetFilter.eq('retailer', retailer);
    }
 
    if (brand) {
        datasetFilter = datasetFilter.eq('brand', brand);
    }
 
    $w('#dataset2').setFilter(datasetFilter);
}

function getBrandDropDown() {
    let result = null;
    // If there is a drop down selected the selectedIndex will be
    // greater than or equal to 0
    if ($w("#dropdown2").selectedIndex >= 0) {
        result = $w("#dropdown2").value;
    }
    return result;
}

function getRetailerDropDown() {
    let result = null;
    // If there is a drop down selected the selectedIndex will be
    // greater than or equal to 0
    if ($w("#dropdown1").selectedIndex >= 0) {
        result = $w("#dropdown1").value;
    }
    return result;
}
  • $w.onReady
    The onReady function set up your main event handlers. I have made a minor change to your original code so that both drop downs can be enabled and used in combination together. I am not sure what the purpose of the genre_change event handler was but it should still work.

  • function resetDropdownsButton_clicked(event)
    This function assumes that you will add a dropdowns reset button $w(‘#resetDropdownsButton’) to clear out the drop down values and reset them to their unselected state. There are other ways to do this but this shows you the code you need.

  • function uniqueDropDown1 ()

  • function uniqueDropDown2 (filter)

  • export function genre_change(event, $w)
    These are your original functions. I have removed the getUniqueTitles and buildOptions functions from the uniqueDropDown1() and uniqueDropDown2() functions and made them first class functions because the code was repetitive.

I have made a minor modification to uniqueDropDown2() where I have added a filter. Your genre_change() event handler uses this with the ‘retailer’ filter to isolate the brand list by retailer. For the solution I have given you you don’t need to do this but you can if you want.

  • function getUniqueTitles(items, columnKey)
    I have modified this slightly so that it can be used by both uniqueDropDown functions. Basically I have added the columnKey argument so that you can create a unique list from an array of objects (items) based on any column key. In this example the keys used are ‘retailer’ and ‘brand’

  • function buildOptions(uniqueList)
    This function wasn’t changed. It has just been removed from the two uniqueDropDown functions and declared once. (Easier to maintain :wink:

  • function dropdownHasChanged(event)
    This function does all of the magic to filter your repeater.


Your repeater is bound to a dataset (dresses 2). The repeater changes its display based on the way the dataset is filtered.

  • So we need to filter the dataset when the dropdown changes. We do this using the ← wix-dataset.setFilter function.

This uses a WixDataFilter to determine which columns to test to limit the items used by the dataset.

We construct a WixDataFilter with the help of the wix-data API. This API has a filter() function --------------------------->

This function returns a WixDataFilter that we can build on.


The WixDataFilter has a number of different helper functions to create some fairly sophisticated filters. We will focus on one though and that is the equals filter or <----------- .eq(). This allows us to ask the dataset to return only those items where the values in the column identified by a column field key (the propertyName) match a test value. e.g:

wixData.filter().eq('retailer', 'ASOS')

We can also add multiple helper functions to filter multiple column values. So to filter on a column field key ‘retailer’ = ‘ASOS’ and column field key ‘brand’ = ‘ASOS DESIGN’. The filter would look like this.

let datasetFilter =  wixData.filter().eq('retailer', 'ASOS').eq('brand', 'ASOS DESIGN');

We can also use a javascript variable to build up the filter which is what we do in the dropdownHasChanged() function. This has added benefits in that if we reset the dropdown values then the filter we create will be empty which will essentially reset the dataset. So the following code results in the same outcome as the snippet before.

let datasetFilter = wixData.filter();
datasetFilter = datasetFilter.eq('retailer', 'ASOS');
datasetFilter = datasetFilter.eq('brand', 'ASOS DESIGN');

Since datasetFilter contains a WixDataFilter we can simply use it as an argument to setFilter.

$w('#dataset2').setFilter(datasetFilter);
  • function getBrandDropDown()

  • function getRetailerDropDown()
    These are convenience or helper functions that look at the dropdown values and determine if there is a value for us to use.

We determine is there is something we can use by checking the selectedIndex property (see image to the right). If this property has a value of 0 or more then we have a value to filter with. NOTE: ----->

To reset the dropdown we need to set this property to undefined. That is what the reset function does for us.

These functions will set their result to the value of the drop down if there is a valid index. Otherwise the result will be null.

The null value forces the if() test in dropdownHasChanged to fail and so the filter for this dropdown value will not be set.

Hope this helps solve your problem!

Steve

@stevendc Hello Steve, I cannot thank you enough for helping me so much. It is truly appreciated. Thank you so much.

I copied and pasted the code to OnClick but for some reason when I click on a retailer’s name or Brand name the repeater is not changing. Do I need to create a separate button for (’ #resetDropdownsButton ')
Here is the link https://www.stylesweetsmile.com/dress

Steve, I have little or no knowledge about coding, so If you think it is too complicated for me to solve can you kindly help me to fix the filter number 1


At the moment when I click on a Brand name the repeater will change but then under brands

  1. Duplicate brand names
  2. After i click a brand (for example Chi Chi London), the repeater will show the dresses relevant to that brand, but as you see on the image Button shows Chi Chi London many times.

I am extremely grateful for all your help.
Thank you,
Dilly

@dilly Hi yes as I mentioned in the post above…
This function assumes that you will add a dropdowns reset button $w(’ #resetDropdownsButton ') .

In addition you had also connected the dropdowns to the dataset using the data bindings. So what was happening is that when the dataset was filtered the bound dropdown settings were being determined from the filtered dataset. Then you were also changing the dropdowns using code. When the code tried to change the dropdown with a different list of values an error was being generated. I have made the changes for you so the site should be functioning the way you want it.

@stevendc Hello Steve,
I cannot thank you enough for the fantastic work that you have done for me in producing exactly the code that has brought everything on my website together.
I am amazed at the way the website is now performing. It is now responding to my clicks very quickly. Thank you again so much for this wonderful gift that you have provided me. Christmas has arrived early for me and it is all thanks to you. My kindest regards to you. I can now enjoy working on my website.

All the best,
Dilly

You are welcome. Can you tag as the Top Comment to let others know that your problem was solved? Thanks
Happy Christmas :wink:

Yes I have tagged you as the top Comment. Thank you so much again for your top class work.