Filter dynamic page content through 2 dropdowns

Good day,
please help with wix corvid code for my site. I have been trying to solve the problem for several days and I do not know what to do.

There is a dynamic page on my website with a list of all football players. Players are displayed and filtered from the collection via a connected dataset. We have several teams for each year (season).

So the URL of the dynamic page is:
www.mysite. com/players/junior/2020/
www.mysite. com/players/junior/2019/
www.mysite. com/players/adults/2020/
www.mysite. com/players/adults/2019/

The dataset filters individual players from the database into the Repeater on the page according to the name of the URL address.

I would like to add 2 dropdowns to the dynamic page. One will display the currently selected team (adult, junior, pupils …) and the other the current selected season (2020, 2019, etc.). I am not able to come up with code for these dropdowns.

Furthermore, when changing the dropdown value (I select a different team or a different year), the page must redirect to a new URL.

I found this example with a list of states and cities. The values ​​are linked to each other and linked into dropdowns. ( https:// codequeen.wixsite. com/dropdown ), but I’m unable to modify it to work as described above.

I tried this code to get a new redirect URL

let NewURL = “/ players /” + $ w (“# dropdown1”). value + “/” + $ w (“# dropdown2”). value;

$ w (“# button1”). link = NewURL;

$ w (“# button1”). target = “_self”;
The problem is that the “value” parameter on dropdown does not return the correct value because it is connected to the dataset.

Thank you so much for any help

Hi Daniel :raised_hand_with_fingers_splayed:

I’m not sure I quite understand why the value returned by the dataset isn’t the correct one, are the dropdowns populated manually, by code or by a dataset?

As far as I can tell, you’re populating them manually, so make sure the values of the dropdown are the same as its labels. (label: junior, value: junior) and not (label: junior, value: item1).

You need to create an onChange() event handler to redirect the visitors to the relevant page.

// Create the event handler
$w('#dropdown1, #dropdown2).onChange((event) => {
    let year = $w("#dropdown2").value;
    let age = $w("# dropdown1").value;
    
    $w("#button1").link = `/players/${age}/${year}`;
})

This will update the link of your button whenever you change the value of the dropdowns.

You can also redirect visitors immediately like this:

import wixLocation from 'wix-location';

$w('#dropdown1, #dropdown2).onChange((event) => {
    let year = $w("#dropdown2").value;
    let age = $w("# dropdown1").value;
    
    wixLocation.to(`/players/${age}/${year}`);
})

Hope this helps~!
Ahmad

Thanks Ahmad for your help! I’m trying, but I’m still not at the finish line.

Therefore, the data for dropdowns must be populated from the database (using a dataset or code). It cannot be done manually. Not every football team (adults, juniors…) has the same year…

https: //www.wix. com/corvid/reference/$w/dropdown/value
Here it is written that "If an element is connected to a dataset, setting the element’s value in code does not set the value of the connected field in the dataset. That means if you use the dataset to perform a submit, the value changed in code is not reflected in the submitted item. "

Second problem: how to display the correct values in dropdowns when the dynamic page is first loaded.

Before the visitor changes the values of dropdowns, the values should correspond to the address of the dynamic page (when I see the list of players “adult” and the year “2019” - the same should show the values of dropdowns)

I’m trying the last code. I like the idea of not using the button, but redirecting visitors whenever the value in the dropdown changes.
I created an onChange () event handler, but it says “parsing error: unterminated string constants”

Thank you for your time, I appreciate any help

Yes, indeed, in form submission changing the the dropdown value doesn’t save the new value to the dataset.

Just let me get them together, what your page suppose to serve? What people suppose to do on these dynamic pages? Also, I didn’t quite understand what the teams have to do with this page if it’s about players?

Please provide as much details as possible, and a link to your site so I can understand the flow better.

@ahmadnasriya
My dynamic page https://www.sokoltouskov. cz/soupiska/a-tym/2019-2020/
shows a list of football players. Retrieves their names and photos from the collection using a dataset.

There are different players for each season. The first dropdown should load a list of all teams. The second dropdown should respond to the first dropdown and display the seasons(years) according to the selected team.

The list of players is generated thanks to the parameters in the URL …/players/a-tym/ 2019-2020/

When I change the dropdown value of a team or season, a new page should load.

When the page first loads, both dropdowns should display the correct value depending on which team and season are being displayed.

This should be the functionality of the dynamic page. I hope I described it well. Thank you

@danvavra Now I understand, the seasons depends on the selected team, right? So when changing the dropdown you need to run a query to get the seasons of that team and then populate the second dropdown with the retrieved results.

Currently, your dropdowns don’t do anything, even the button link isn’t being changed.

@ahmadnasriya Yes exactly. The seasons depends on the selected team.

I found this example with a list of states and cities. I think it could be used for my teams and seasons. The values are linked to each other and linked into dropdowns. (https: codequeen.wixsite. com / dropdown), but I’m unable to modify it to work as described above.

It’s also not clear to me how I get the values from the dynamic page URL (ie the currently selected team and season) into the dropdowns value. In order for the first time you open the page, the content of the footballers displayed with the value displayed in the dropdowns will be identical.

@danvavra You don’t take the values from the URL itself, rather extract them from the dataset itself.

$w('#dataset').onReady(async() => {
    const item = $w('#dataset').getCurrentItem();
    const team = item.team;
    $w('#teams').value = team;
    
    /* Now we have the team of the player, let's query
    the collection and get the seasons available of this team */
    await wixData.query('collection').eq('team', team).distinct()
    .then((result) => {
            
        let seasons = [];
        for (let i = 0; i < result.length; i++) {
            let season = result.items[i].season;
            seasons.push(season);
        }
        $w('#seasons').options = seasons;
    })    
})

Hope you find it useful.

Hi @Ahmad ,
thank you very much for your help. The code was useful and helped. In the end, I solved the problem with the help of your code and code from “Code Queen”.

Thanks again for the help and your time
Check https://www.sokoltouskov. cz/soupiska/a-tym/2020-2021

It’s just interesting that filling and assigning the current dropdown value takes about 1 second after the page loads. Visitors can flash the values in dropdowns.

Now I have set the “wixLocation. to” command to be executed whenever the value in the dropdowns changes. I don’t use the push button. And now I have come to an anomaly. The “wixLocation. to” command is executed before the corresponding “season-year” value is filled into the dropdown. This causes the visitor to be redirected to a page that may not exist. The dropdown command is preceded by a page redirection command.

export function dropdownTeam_change(event) {
wixData.query(“Sezona”)
.contains(“tym”, $w(“#dropdownTeam”).value)
.limit(100)
.find()
.then(results => {
const uniqueTitles = getUniqueTitles(results.items);
$w(“#dropdownSeason”).options = buildOptions(uniqueTitles);
});
function getUniqueTitles(items) {
const titlesOnly = items.map(item => item.sezona);
return […new Set(titlesOnly)];
}
function buildOptions(uniqueList) {
return uniqueList.map(curr => {
return {label:curr, value:curr};
});
}

const AktualniTym = $w(‘#dropdownTeam’).value
const AktualniSezona = $w(‘#dropdownSeason’).value
wixLocation.to(/soupiska/${AktualniTym}/${AktualniSezona});
}

Thanks for trying out my tutorials.

I hope you don’t mind, but I took a look at your entire page code from the link you shared even though you only posted partial code from that page.

The syntax of your code is correct but your code has a lot of conflicting logic that should be polished up. Let’s start from the top. Without changing your code yet, I want to walk you through some things:

For both dropdowns you are doing 2 things, you are getting current Item of the dynamic page to ‘set the value’ but at the same time you are querying the database to look FOR the values. So you are basically setting the value before the options of values is even determined.

import {session} from 'wix-storage';
import wixLocation from 'wix-location';

let previousPageURL;


$w.onReady(function () {

    previousPageURL = session.getItem("page");
    console.log(previousPageURL);
    session.setItem("page", wixLocation.url);
    $w("#btnBack").link = previousPageURL;
    $w("#btnBack").target = "_self";

    uniqueDropDown1();  // popis
    uniqueDropDown2();


 const item1 = $w('#dynamicDataset').getCurrentItem();
 const AktualniTym = item1.newField;  //sloupec Tým se jmenuje newField
    $w('#dropdownTeam').value = AktualniTym;
    $w('#text40').text = AktualniTym;

 const item2 = $w('#dynamicDataset').getCurrentItem();
 const AktualniSezona = item2.sezona;
    $w('#dropdownSeason').value = AktualniSezona;
 //$w('#text40').text = AktualniSezona;

});

Then we have the query for both dropdowns to get the unique possible options (aka the values). As we noticed above, you triggered both of these at the same time inside of the onReady. The first one is trying to find the values for the dropdownTeam, and the second is trying to find the values for the Season that match the dropdownTeam. Again, you are trigger a code based on a value that is neither selected nor determined yet.

function uniqueDropDown1 (){
    wixData.query("Sezona") // připojení k DB
        .limit(100)
      .find()
      .then(results => {
 const uniqueTitles = getUniqueTitles(results.items);
           $w("#dropdownTeam").options = buildOptions(uniqueTitles); // naplň nabídku unikátními hodnotami neopakujicimi se
      });
 function getUniqueTitles(items) {
 const titlesOnly = items.map(item => item.tym);  //fieldkey nazev v DB
 return [...new Set(titlesOnly)];
    }
 function buildOptions(uniqueList) {
 return uniqueList.map(curr => {
 return {label:curr, value:curr};
        });
    }
}

function uniqueDropDown2 (){
    wixData.query("Sezona")
        .contains("tym", $w("#dropdownTeam").value)
        .limit(100)
      .find()
      .then(results => {
 const uniqueTitles = getUniqueTitles(results.items);
           $w("#dropdownSeason").options = buildOptions(uniqueTitles);
      });
 function getUniqueTitles(items) {
 const titlesOnly = items.map(item => item.sezona); // city druhy nazev v DB
 return [...new Set(titlesOnly)];
    }
 function buildOptions(uniqueList) {
 return uniqueList.map(curr => {
 return {label:curr, value:curr};
        });
    }
}

And finally we have the last part of the code. This is where you are trying to get values from both dropdowns to create a URL and then redirect person to that URL. The problem here is that you triggered the navigation onChange (when the dropdownTeam changes) before the 2nd dropdown value is selected or determined. Same problem with the 2nd dropdown, you have also triggered the navigation as soon as the dropdown changes. Then you have the navigation code again upon button click. The problem with the button click is, as soon as the person changes 1 of the dropdowns the code will trigger the navigation meaning they will never get to select the 2nd dropdown and they will never get to click the button.

export function dropdownTeam_change(event) {
 // Naplněný druhého dropdownu daty s roky
 //uniqueDropDown2(); 
   wixData.query("Sezona")
        .contains("tym", $w("#dropdownTeam").value)
        .limit(100)
      .find()
      .then(results => {
 const uniqueTitles = getUniqueTitles(results.items);
           $w("#dropdownSeason").options = buildOptions(uniqueTitles);
      });
 function getUniqueTitles(items) {
 const titlesOnly = items.map(item => item.sezona); // city druhy nazev v DB
 return [...new Set(titlesOnly)];
    }
 function buildOptions(uniqueList) {
 return uniqueList.map(curr => {
 return {label:curr, value:curr};
        });
    }


 const AktualniTym = $w('#dropdownTeam').value
 const AktualniSezona = $w('#dropdownSeason').value    
    wixLocation.to(`/soupiska/${AktualniTym}/${AktualniSezona}`);

}

export function dropdownSeason_change(event) {
 // Add your code for this event here: 

 const AktualniTym = $w('#dropdownTeam').value
 const AktualniSezona = $w('#dropdownSeason').value    
    wixLocation.to(`/soupiska/${AktualniTym}/${AktualniSezona}`);


}

export function nacti_click(event) {
 // Add your code for this event here: 

 // Pro případ změny 
 let season = $w("#dropdownSeason").value;
 let team = $w("#dropdownTeam").value;
 
    wixLocation.to(`/soupiska/${team}/${season}/`);
}

Now I am going to remove a few lines of code and share it with you. If you use the code like this then you must disable Season dropdown on load, and delete the button because the code will enable the 2nd dropdown and the navigation will happen after the user selects a value from the 2nd dropdown:

$w.onReady(function () {

    previousPageURL = session.getItem("page");
    console.log(previousPageURL);
    session.setItem("page", wixLocation.url);
    $w("#btnBack").link = previousPageURL;
    $w("#btnBack").target = "_self";

    uniqueDropDown1();  // popis

 const item1 = $w('#dynamicDataset').getCurrentItem();
    $w('#text40').text = AktualniTym;

});

function uniqueDropDown1 (){
    wixData.query("Sezona") // připojení k DB
        .limit(100)
      .find()
      .then(results => {
 const uniqueTitles = getUniqueTitles(results.items);
           $w("#dropdownTeam").options = buildOptions(uniqueTitles); // naplň nabídku unikátními hodnotami neopakujicimi se
      });
 function getUniqueTitles(items) {
 const titlesOnly = items.map(item => item.tym);  //fieldkey nazev v DB
 return [...new Set(titlesOnly)];
    }
 function buildOptions(uniqueList) {
 return uniqueList.map(curr => {
 return {label:curr, value:curr};
        });
    }
}

function uniqueDropDown2 (){
    wixData.query("Sezona")
        .contains("tym", $w("#dropdownTeam").value)
        .limit(100)
      .find()
      .then(results => {
 const uniqueTitles = getUniqueTitles(results.items);
           $w("#dropdownSeason").options = buildOptions(uniqueTitles);
      });
 function getUniqueTitles(items) {
 const titlesOnly = items.map(item => item.sezona); // city druhy nazev v DB
 return [...new Set(titlesOnly)];
    }
 function buildOptions(uniqueList) {
 return uniqueList.map(curr => {
 return {label:curr, value:curr};
        });
    }
}

export function dropdownTeam_change(event) {
 // Naplněný druhého dropdownu daty s roky
    uniqueDropDown2(); 
    $w('#dropdownSeason').enable();    
}

export function dropdownSeason_change(event) {
 const AktualniTym = $w('#dropdownTeam').value
 const AktualniSezona = $w('#dropdownSeason').value    
    wixLocation.to(`/soupiska/${AktualniTym}/${AktualniSezona}`);
}

But if you want to trigger the navigation from the button instead of the 2nd dropdown, then the code will look like this:

$w.onReady(function () {

    previousPageURL = session.getItem("page");
    console.log(previousPageURL);
    session.setItem("page", wixLocation.url);
    $w("#btnBack").link = previousPageURL;
    $w("#btnBack").target = "_self";

    uniqueDropDown1();  // popis

 const item1 = $w('#dynamicDataset').getCurrentItem();
    $w('#text40').text = AktualniTym;

});

function uniqueDropDown1 (){
    wixData.query("Sezona") // připojení k DB
        .limit(100)
      .find()
      .then(results => {
 const uniqueTitles = getUniqueTitles(results.items);
           $w("#dropdownTeam").options = buildOptions(uniqueTitles); // naplň nabídku unikátními hodnotami neopakujicimi se
      });
 function getUniqueTitles(items) {
 const titlesOnly = items.map(item => item.tym);  //fieldkey nazev v DB
 return [...new Set(titlesOnly)];
    }
 function buildOptions(uniqueList) {
 return uniqueList.map(curr => {
 return {label:curr, value:curr};
        });
    }
}

function uniqueDropDown2 (){
    wixData.query("Sezona")
        .contains("tym", $w("#dropdownTeam").value)
        .limit(100)
      .find()
      .then(results => {
 const uniqueTitles = getUniqueTitles(results.items);
           $w("#dropdownSeason").options = buildOptions(uniqueTitles);
      });
 function getUniqueTitles(items) {
 const titlesOnly = items.map(item => item.sezona); // city druhy nazev v DB
 return [...new Set(titlesOnly)];
    }
 function buildOptions(uniqueList) {
 return uniqueList.map(curr => {
 return {label:curr, value:curr};
        });
    }
}

export function dropdownTeam_change(event) {
 // Naplněný druhého dropdownu daty s roky
    uniqueDropDown2(); 
    $w('#dropdownSeason').enable();    
}

export function nacti_click(event) {
 // Add your code for this event here: 

 // Pro případ změny 
 let season = $w("#dropdownSeason").value;
 let team = $w("#dropdownTeam").value;
 
    wixLocation.to(`/soupiska/${team}/${season}/`);
}

If you want to check out my other tutorials, I have one about navigation using a dropdown element: https://www.totallycodable.com/example-dropdown-navigation

Hey Daniel :raised_hand_with_fingers_splayed:

Glad that it was helpful …
By the way, do you know that there’s already a method to return the unique items called distinct() . It will save you time and make the page faster.

Use it on your existing query like this:

await wixData.query("Sezona").contains("tym", $w("#dropdownTeam").value)
        .limit(100)
        // This will return unique items of the below field
        .distinct("sezona")        
        .then((result) => {
                $w("#dropdownSeason").options = result.items;
                // Which are already unique. 😉                
        })

Don’t place the redirection command inside the onReady() function, you don’t want them to be redirected immediately once the page is ready, you need to create an onChange() event handler that will redirect the visitors only if a value is selected, and disable the seasons dropdown while no team is selected.

First of all, set the seasons dropdown to be disabled on load by un-checking the mark in the dropdown properties panel that says “Enabled on load”, then add the event handlers.

$w('#dropdownTeams').onChange((event) => {
    if (!$w('#dropdownSeason').enabled) {
        $w('#dropdownSeason').enable();
    }
})

$w('#dropdownSeason').onChange((event) => {
    let team = $w('#dropdownTeams').value;
    let season = $w('#dropdownSeason').value;
    
    $w('#dropdownSeason').disable().then(() => {
        wixLocation.to(`/soupiska/${team}/${season}`);
    })
})

This way, they won’t be redirected unless they choose a season.

Hope this helps~!
Ahmad

@ahmadnasriya Can you check on this post →
https://www.wix.com/corvid/forum/community-discussion/typeerror-error-capturestacktrace-is-not-a-function

@ajithkrr Will do …

Thank you for the explanation @code-queen and also @ahmadnasriya for the advice. The site is already working.

I still tried the distinct method for returning unique items, but the code doesn’t work. Wix SDK error: The selectOption parameter of an item at index 0 that is passed to the options method cannot be set to 2019-2020. It must be an object type.
I stayed with the original code.

You’re welcome @danvavra , don’t mention it :wink:
Very strange :thinking: Did you follow the instructions provided in the link above? It should work. Anyways, good to hear that your website is working now, if you ever need help just tag me in your posts.