Checkbox Filter Using Search Button > Appear on Lightbox with Repeater

I’m building a search filter feature on my healthy products website but I stuck and need help with the code .
The main objective of the filter is to search a correct product correspond to the specific symptoms .

I’m going to explain all the information as much detail as I can and keep in mind I’m not a developer, so please answer it like you’re talking to a non-coder person (although I can read really-really basic code).

~Thank you in advance


PAGE STRUCTURE & ELEMENT

Main Page = consist of almost all the elements, including:

  • Container Box (#box1) : for containing #repeater1

  • Repeater (#repeater1) : for containing #checkbox1 and #text1

  • Single Checkbox (#checkbox1) : I used an empty single checkbox (not a group checkbox and has no value) to customize the layout (border, fill, color, position, etc.). Because if I use template checkbox, I can’t customize the design later

  • Text (#text1) : Because of the #checkbox1 has no value and needed to load the value (symptoms) later, this text also link to the same collection to load ‘Collection 2’ about symptoms name

  • Search Button (#button1): a triggered click to start the filter process → it will open the #lightboxResult and show the result on #repeaterResult

  • Clear Button (#clearButton) : to clear all the checkboxes and query

Lightbox Page = only consist of the result of the filter function above

  • Lightbox (#lightboxResult) : for containing #repeaterResult

  • Repeater (#repeaterResult) : for the result of the filter. The dataset shows each field from ‘Collection 1’

  • Text (#productResult) : for the product filter result

  • Text (#symptomResult) : for the symptoms name filter result Close button


COLLECTION & DATASET

Collection 1 (ID: Products)
Field 1 (type: Text / key: title) : for the product name. A product can be used on more than 1 symptoms
Field 2 (type: Tags / key: symptoms) : filled with the symptoms correspond to the products. It can consist more than 1 symptom per product

Collection 2 (ID: Symptoms)
Field 1 (type: Text / key: name) : consist of all symptoms name. It is a basic data to fill all the #checkbox1 & #text1 value


LOGIC & FUNCTION

Function 1
Load all the symptoms name (‘name’) from the Collection 2 (‘Symptoms’) and add it to the #checkbox1 & #text1 list

Function 2
#checkbox1 selected > filter the products that contain any of the selected symptoms based on the data on Collection 1 (‘Products’)

Function 3
Search Button #button1 clicked > show #lightboxResult and call the #repeaterResult to show all the correspond products from the filter


CODE

I manage to write a code until some point. The Function 1 and Function 2 works fine, but the result query is showing on the same page in a repeater. But when I try to make Function 3, I got stuck. The result query won’t show on the Lightbox page within the #repeaterResult. It just showing all the data from the collection instead.

Here’s the code:

import wixData from 'wix-data';
import wixWindow from 'wix-window';

$w.onReady(() => {
    setupRepeater();
    loadSymptoms();
});

function setupRepeater() {
    $w('#repeater1').onItemReady(($item, itemData) => {
        $item('#checkbox1').onClick(() => {
            searchCB();
        });
        $item('#text1').text = itemData.value;
    });
}

function loadSymptoms() {
    wixData.query('Symptoms')
        .find()
        .then(results => {
            $w('#repeater1').data = [];
            let symptomsDropdownOptions = [];
            symptomsDropdownOptions.push(...results.items.map(symptoms => {
                return { _id: symptoms._id, value: symptoms.title, label: symptoms.title };
            }));
            $w('#repeater1').data = symptomsDropdownOptions;
        });
}

let symptomsCB = [];

function searchCB() {
    $w('#repeater1').forEachItem(($item, itemData, index) => {
        if ($item('#checkbox1').checked) {
            symptomsCB.push($item('#text1').text);
        }
    });
}

export function searchButton3_click(event) {
    symptomsCB = [];
    $w('#repeater1').forEachItem(($item, itemData, index) => {
        if ($item('#checkbox1').checked) {
            symptomsCB.push($item('#text1').text);
        }
    });
    
    let query = wixData.query("Products");
    for (let i = 0; i < symptomsCB.length; i++) {
        query = query.hasAll("symptoms", symptomsCB[i]);
    }
    
    query.find().then(results => {
        // Filter the results based on the selected symptoms
        const filteredResults = results.items.filter(item => {
            return symptomsCB.every(symptom => item.symptoms.includes(symptom));
        });
        
        // Assign the filtered results to the repeater in Lightbox1
        wixWindow.openLightbox("LightboxResult").then(() => {
            $w('#repeaterResult').data = filteredResults;
        });
    });
}

$w.onReady(() => {
    $w('#clearButton').onClick(() => {
        $w("#repeater1").data.forEach(item => {
            $w("#checkbox1").checked = false;
        });
        $w("#dataset1").setFilter(wixData.filter());
    });
});

That’s all, and please kindly help me.
~ Thank you

Step-1: Getting-Data + Generating CHB-List…

Till here …

import wixData from 'wix-data';

// ----------USER-INTERFACE------------------
const dbProducts = "Products";
const dbSymptoms = "Symptoms";
const REP1 = "#repeater1 ";
const CHB1 = "#checkbox1"; 
// ----------USER-INTERFACE------------------

let symptomsCB = [];

$w.onReady(async() => {
    //Preparing first REPEATER with data from "Symptoms"-DB first..
    //...and feed repeater1 with this data...
    let symptomData = await loadSymptoms(dbSymptoms);
    console.log("Symptoms: ", symptomData);
    //reset of repeater...
    $w(REP1).data = [];
    //feed repeater with returned data...
    $w(REP1).data = symptomData;


    $w(REP1).onItemReady(($item, itemData, index) => {
        $item('#text1').text = itemData.value;
        $item(CHB1).onClick(async()=> {get_Symptoms();});
        $item('#text1').text = itemData.value;
    });
});

function loadSymptoms(DB) {
    wixData.query(DB)
    .find()
    .then(results => {
        let symptomsDropdownOptions = [];
        symptomsDropdownOptions.push(...results.items.map(symptoms => {
            return { _id: symptoms._id, value: symptoms.title, label: symptoms.title };
        }));
        return symptomsDropdownOptions;
    });
}

… everything looks not bad.

You get data from SYMPTOMS-DB and feed your REPEATER1 with all the data from SYMPTOMS-DB, to generate your dynamic Check-Box-List.

Step-2: Click onto a repeated-item → searchCB()

Part of already coded part above… → the click to start all the process…

$item(CHB1).onClick(()=> {searchCB();});

Attention the name of the function has been changed in this example…

function get_Symptoms() {
    $w('#repeater1').forEachItem(($item, itemData, index) => {
        let text = $item('#text1').text;        
        if ($item('#checkbox1').checked) {
            symptomsCB.push(
               {id:$item('#checkbox1').id, value:text, label:text}
            );
        }
    });
}

You got all your selected SYMPTOMS from your REPEATER now!

Step-3: Click the SEARCH-Button to start the search…

!!! AND HERE IT IS —> YOUR ERROR !!!

export function searchButton3_click(event) {---> symptomsCB = [];

First you do a lot to get all the selected values putting them into an ARRAY!!!
But when starting your → SEARCH <— —> you FIRST RESET the ARRAY ???

Ok, i think you should REWRITE further CODE-PARTS (rewrite your —>

export function searchButton3_click(event) {.........

…putting it also into the onReady()-Main-Block …

$w.onReady(async() => {
    // already generated code ...
    // code ...
    // code ...
    // code ...
    
    $w('#button1').onClick(()=>{
        FUNCTION3();
    });
});

Another aspect —> If you are using a DATASET-CONNECTION → do not for get to add…

$w.onReady(async() => {
    $w('#dataset1').onReady(()=>{});
    // already generated code ...
    // code ...
    // code ...
    // code ...
    
        $w('#btnSearch').onClick(()=>{
            start_SearchFunction();
        });
    });
});

Also use just logical element-IDs :
#button1 ----------------------------------------> BAD !!!
#btnSearch ------------------------------------> GOOD !!!

Now try to get all that done and complete your task !!!

!!! Good luck and happy coding !!!

Code-Ninja

Hey, first of all, thank you for responding to my question, appreciated it man.
I’ve followed all your code as much as I can understand (as I mentioned before I’m not a devs nor have coding background, sry lol).

But some issues appear:

  • The symptoms name doesn’t load into the checkbox list
  • The search button doesn’t call the lightbox and so the result

Here’s my updated code:

import wixData from 'wix-data';
import wixWindow from 'wix-window';

//---------- USER INTERFACE ----------
const dbProducts = "Products";
const dbSymptoms = "Symptoms";
const REP1 = "#repeater1";
const CHB1 = "#checkbox1";

let symptomsCB = [];

//---------- FUNCTION 1 ----------
$w.onReady(async () => {

    let symptomData = await loadSymptoms(dbSymptoms);
    console.log("Symptoms: ", symptomData);

    $w(REP1).data = [];

    $w(REP1).data = symptomData;

    $w(REP1).onItemReady(($item, itemData, index) => {
        $item('#text1').text = itemData.value;
        $item(CHB1).onClick(async () => { get_Symptoms(); });
        $item('#text1').text = itemData.value;
    });
});

function loadSymptoms(DB) {
    wixData.query(DB)
        .find()
        .then(results => {
            let symptomsDropdownOptions = [];
            symptomsDropdownOptions.push(...results.items.map(symptoms => {
                return { _id: symptoms._id, value: symptoms.title, label: symptoms.title };
            }));
            return symptomsDropdownOptions;
        });
}

//---------- FUNCTION 2 ----------
function get_Symptoms() {
    $w("#repeater1").forEachItem(($item, itemData, index) => {
        let text = $item('#text1').text;
        if ($item("#checkbox1").checked) {
            symptomsCB.push({ id: $item(CHB1).id, value: text, label: text });
        }
    });
}

//---------- FUNCTION 3 ----------
$w.onReady(async () => {
    function searchFunction() {
        $w(REP1).forEachItem(($item, itemData, index) => {
            if ($item(CHB1).checked) {
                symptomsCB.push($item('#text1').text);
            }
        });

        let query = wixData.query(dbProducts);

        for (let i = 0; i < symptomsCB.length; i++) {
            query = query.hasAll("symptoms", symptomsCB[i]);
        }

        query.find().then(results => {
            const filteredResults = results.items.filter(item => {
                return symptomsCB.every(symptom => item.symptoms.includes(symptom));
            });

            wixWindow.openLightbox("Lightbox1").then(() => {
                $w('#repeaterLB').data = filteredResults;
            });
        });
    }

    $w('#searchButton').onClick(() => {
        searchFunction();
    });
});

//---------- FUNCTION 4 ----------
$w.onReady(() => {
    $w('#clearButton').onClick(() => {
        $w(REP1).data.forEach(item => {
            $w(CHB1).checked = false;
        });
        $w("#dataset1").setFilter(wixData.filter());
    });
});

Can you please kindly check it again? Thank you~

But some issues appear:

  • The symptoms name doesn’t load into the checkbox list

Yes, that’s right → i did not pay attention onto the ID of your NAME-Field inside the SYMPTOM-DATABASE.
But normaly you should be able to find this little bug on your own…
If you would use some more console-logs → it would be much easier for you to → DEBUG <— your own code.

See here an EXAMPLE: …

function loadSymptoms(DB){
	wixData.query(DB).find().then(results=>{
 	let symptomsDropdownOptions=[];
	symptomsDropdownOptions.push(...results.items.map(symptoms=>{
	return{_id:symptoms._id,value:symptoms.tifunction loadSymptoms(DB){
    wixData.query(DB).find()
    .then(results=>{console.log("RESULTS: ", results);
        let symptomsDropdownOptions=[];
        symptomsDropdownOptions.push(
            ...results.items.map(symptoms=>{
            return{_id:symptoms._id,value:symptoms.name,label:symptoms.name};}
            )
        );
        console.log("OPTIONS: ", symptomsDropdownOptions);
    return symptomsDropdownOptions;});
}tle,label:symptoms.title};
})
);
	return symptomsDropdownOptions;});
}

Before:

symptoms.title

After:

symptoms.name

Since you have the data inside of the → NAME-field <— and not inside the —> TITLE-field <---- .

Also implement some console.log → console.log("RESULTS: ", results);
To be able to understand whats happening inside of your own code at which code-position.

The more console.logs you use —> the faster you will be able to solve your issue.

Issue resolved?

I think it’s not the problem because I had the Key Field using “title”, not “name”.
That field is changed by me for the purpose of this thread.
The actual key field is still “title”:

From the console log I got that:

So does it mean the function:

letsymptomData=awaitloadSymptoms(dbSymptoms);

doesn’t work?

Not yet. still wondering which part is wrong

Ok, i will reconstruct your issue to demonstrate you how to do all these steps and codings the right way.

Do me a favour… NEVER do such things again in your SETUP and codings…


Never name your field different then it’s corresponding ID.

If the Field-Name = “Banana-Field” —> then ID = bananaField.
If the Field-Name is “Apple-Field” -----> then the ID of that field is → “appleField”

This is normaly automatically generated, don’t change such things.
That will save a lot of headaches!!!

The best coding is a → short, dynamic, efficient, logical and systematic coding .

  1. Never use to long variable declarations (try to keep your code short and clean).
  2. Try always to code variable and dynamic.
  3. Try always to code systematical and logical → this will keep your code always better readable → faster working with code.

Conclusion —> more efficient and faster CODING-PROCESS !!!
Less failures, errors and code-bugs, less waste of time!!!

Try this one…
See if this works for you.
If it works, understand it first, before you start to add more codings…


import wixWindow from 'wix-window';

//---------- USER INTERFACE ----------
const dbProducts = "Products";
const dbSymptoms = "Symptoms";

$w.onReady(async()=> {
    //getting SYMPTONS-DATA...
    //-----------------------
    let symptomData = await loadSymptoms(dbSymptoms);
    console.log("Symptoms: ", symptomData);

    //resetting your repeater...
    //-----------------------
    $w("#repeater1").data = [];

    //feeding your repeater with found SYMPTOMS-DATA...
    //-----------------------
    $w("#repeater1").data = symptomData;

    //Do actions, when repeater loads (has loaded) items...
    //-----------------------
    $w("#repeater1").onItemReady(($item,itemData,index)=>{
        console.log("Item-Data: ", itemData);
        $item('#text1').text = itemData.value;
        $item('#checkbox1').onClick(async()=> { 
            let foundSymptoms = await get_Symptoms(); 
            console.log("Found-Symptoms: ", foundSymptoms);
            $w("#resultRepeater").data = foundSymptoms;
        });
        $item('#text1').text = itemData.value;
    });
        
    $w("#resultRepeater").onItemReady(($i,iData,index)=>{
        //...complete result-repeater-code...
        //...complete result-repeater-code...
        //...complete result-repeater-code...
        //...complete result-repeater-code...
        //...complete result-repeater-code...
    });

    //-----------------------
    $w('#clearButton').onClick(() => {
        $w("#repeater1").forEachItem(($item) => {
            $item('#checkbox1').checked = false;
        });
    });
});


//---------- FUNCTION-1 ----------
function loadSymptoms(DB) {
    return wixData.query(DB)
    .find()
    .then(results => {
        let symptomsDropdownOptions = [];
        symptomsDropdownOptions.push(...results.items.map(symptoms => {
            return { _id: symptoms._id, value: symptoms.title, label: symptoms.title };
        }));
        return symptomsDropdownOptions;
    });
}

//---------- FUNCTION-2 ----------
function get_Symptoms() {
    let symptomsCB = [];
    $w("#repeater1").forEachItem(($item,itemData,index) => {
        let text = $item('#text1').text;
        if ($item("#checkbox1").checked) {
            symptomsCB.push({id:itemData._id, value:text, label:text});
            return symptomsCB;
        }
    });
}

Not tested !!!

Pay attention onto CONSOLE-LOGS,they will help you to understand the CODE…
Add more logs into your CODE —> if needed for further investigations…

This example do not include the LIGHTBOX-functionality.
This example do not include the SEARCH-FUNCTION.
This example works without DATASET-CONNECTIONS.