Filtering a Repeater On Many To Many Relationship Data

So, I’m creating a recipe search where a person can filter my recipes based on the ingredients. This is a many-to-many relationship, in that a recipe has lots of ingredients and an ingredient can be present in more than one recipe. An abbreviated data diagram is below.


I’ve added the ingredient dropdown filter (dropdown1) to my page, and the recipe repeater (repeater1). The challenge I’m having is that I’m struggling to get the code to work for the nested query. What should happen is that when the user selects an ingredient from the dropdown field, only recipes with that ingredient will be displayed. Here’s what I have

import wixData from ‘wix-data’;

let selectedingredient = “”;
let selectedrecipe = “”;

export function dropdown1_change(event, $w) {
wixData.query(“Ingredient_Tbl”)
.eq(“Title”,$w(“#dropdown1”).value)
.find()
.then((results) => {
let firstitem = results.items[0];
selectedingredient = firstitem._id;

    	wixData.query("IngredientRecipe_Tbl") 
    	.eq("ingredient",selectedingredient) 
    	.find() 
    	.then((results) => { 
    		let seconditem = results[0] 
                    selectedrecipe = seconditem._id; 
    		
    		wixData.query("Recipe_Tbl") 
    		.eq("title",selectedrecipe) 
    		.find() 
    		.then((result) => { 
    			$w("#repeater1").data = result.items; 
    		}) 
    	}) 
    .catch( (err) => { 
    	let errorMsg = err; 
    }); 
}); 

}

Anybody able to help me work out what I should change to make it behave, please

Hi,
I’ve copied the code and added some notes:

export function dropdown1_change(event, $w) {
	wixData.query("Ingredient_Tbl")
	     //the field key is "title", not "Title"
	    .eq("Title",$w("#dropdown1").value)
	    .find()
	    .then((results) => {
	    	let firstitem = results.items[0];
	    	selectedingredient = firstitem._id;
	    	wixData.query("IngredientRecipe_Tbl")
	    	.eq("ingredient",selectedingredient)
	    	.find()
	    	.then((results) => {
			//here it should also be results.items[0];
	    		let seconditem = results[0]
                        selectedrecipe = seconditem._id;
	    		wixData.query("Recipe_Tbl")
	    		.eq("title",selectedrecipe)
	    		.find()
	    		.then((result) => {
	    			$w("#repeater1").data = result.items;
	    		})
	    	})
	    .catch( (err) => {
	    	let errorMsg = err;
	    });
	});
}

I recommend checking out also this article to learn more about debugging your site’s code.
Should the issue persists, please send us the site URL and the page name so that we can have a look.

Have a good day,
Tal.

So, it appears Wix doesn’t use relational databases. I go this working using the following workaround.

  1. Create a Database collection with items that you want to appear in your dropdowns (e.g. I want to filter gemstones by colour, origin and typical transparency). Populate this list and ensure you include an option *All
  2. For your item (gemstones) collection, ensure you have a text column that matches each of the filters (e.g. GemstoneColour, GemstoneOrigin, GemstoneClarity).
  3. In these columns, list all the relevant information and make sure you include *All
  4. On page, add your filter boxes (named colourselect, clarityselect and countryselect) and include the following code:

export function dropdown_change(event, $w) {
wixData.query(“Gemstone”)
.contains(“showOrHide”,‘Show’)
.contains(“GemstoneColour”,$w(“#colourselect”).value)
.contains(“GemstoneClarity”,$w(“#clarityselect”).value)
.contains(“GemstoneOrigin”,$w(“#countryselect”).value)
.ascending(“title”)
.find()
.then( (results) => {
$w(“#repeater1”).data = results.items;
} )
.catch( (err) => {
let errorMsg = err;
} );
}

  1. Link this code to the on_change function for all your dropdowns.
  2. Now you only need to change the text in the database collection fields and it will automatically change which filters they appear under.
  3. Notice, I’ve also added a Show/Hide field to each stone to make it easy to manage what people see.

Now your users can easily filter what they see. A great option for letting people filter a portfolio by a style or subject, or recipes by meal or ingredient.

But, what happens when your user wants to reset these filters…

Easy! Create a text field called “Clear All” and link it to the following code.

export function clearfilters_click(event, $w) {
$w(“#colourselect”).value = ‘*All’;
$w(“#clarityselect”).value = ‘*All’;
$w(“#countryselect”).value = ‘*All’;
wixData.query(“Gemstone”)
.contains(“showOrHide”,‘Show’)
.contains(“GemstoneColour”,$w(" #colourselect “).value)
.contains(“GemstoneClarity”,$w(” #clarityselect “).value)
.contains(“GemstoneOrigin”,$w(” #countryselect “).value)
.ascending(“title”)
.find()
.then( (results) => {
$w(”#repeater1").data = results.items;
} )
.catch( (err) => {
let errorMsg = err;
} );
}

This sets all the dropdown values to *All and refreshed the repeater.

Thank you for your code. I have tried to set this to my page to filter my collection. Unfortunately it doesn’t work. This is my code:

import wixData from ‘wix-data’;
import wixLocation from ‘wix-location’;
export function artcatdropdown_change(event,$w) {
wixData.query(“Artworks”)
.contains(“artCategory”,$w(“#artcatdropdown”).value)
.ascending(“title”)
.find()
.then( (results) => {
$w(“#searchrep”).data = results.items;
} )
. catch ( (err) => {
let errorMsg = err;
} );
}

export function styledropdown_change(event) {
wixData.query(“Artworks”)
.contains(“style”,$w(“#styledropdown”).value)
.ascending(“title”)
.find()
.then( (results) => {
$w(“#searchrep”).data = results.items;
} )
. catch ( (err) => {
let errorMsg = err;
} );
}

export function mediumdropdown_change(event) {
wixData.query(“Artworks”)
.contains(“medium”,$w(“#mediumdropdown”).value)
.ascending(“title”)
.find()
.then( (results) => {
$w(“#searchrep”).data = results.items;
} )
. catch ( (err) => {
let errorMsg = err;
} );
}
export function clearfilters_click(event, $w) {
$w(“#artcatdropdown”).value = ‘All’;
$w(“#styledropdown”).value = ‘All’;
$w(“#mediumdropdown”).value = ‘All’;
wixData.query(“Artworks”)
.contains(“showhide”,‘true’)
.contains(“artCategory”,$w(“#artcatdropdown”).value)
.contains(“style”,$w(“#styledropdown”).value)
.contains(“medium”,$w(“#mediumdropdown”).value)
.ascending(“title”)
.find()
.then( (results) => {
$w(“#searchrep”).data = results.items;
} )
. catch ( (err) => {
let errorMsg = err;
} );
}

Can you help me, what can be the problem? I see the filters on the page, but when I select one filter for a selection with no result and than back to a selection with valid results is show no items. Thanks. Ildiko

Thank you for your code suggestion. I have implemented it on my site, but unfortunately it doesn’t work. Can you help me? I have placed my code in the below comment. Thanks. Ildiko

Hi,
This is an old thread. Can you please post a new post with your question? Moreover, a video of the issue can be helpful too. You can use screencast for that purpose. Simply recreate the issue while recording the steps add the screencast.com URL to your response.

Thanks,
Tal.