I am trying to create a select dropdown filter which dynamically gets its values and data from rest api.
Here is my code
HTML
<div class="container"> <select data-filter="season" class="filter_category_name filter form-control"></select> <div class="listContent" id="listitem"></div> </div>
JS
var data = [{ "category_name": "1", "title": "One One", "more": [{ "details": "some details" }] }, { "category_name": "1", "title": "One Two", "more": [{ "details": "some details" }] }, { "category_name": "2", "title": "Two One", "more": [{ "details": "some details" }] }, { "category_name": "3", "title": "Three One", "more": [{ "details": "some details" }] }]; let listItems = "", categoryAll = ""; for(var i = 0;i < data.length; i++) { var title = data[i].title, category_name = data[i].category_name; listItems += "<a onclick='createAVideoContainer(" + i + ")'><div class='listItem'><p>" + title + "</p></div></div></a>"; if (categoryAll.indexOf("<option value='" + category_name + "'>" + category_name + "</option>") == -1) { categoryAll += "<option value='" + category_name + "'>" + category_name + "</option>"; } } $("#listitem").html(listItems); $(".filter_category_name").append(categoryAll); var filtersObject = {}; $(".filter").on("change",function() { var filterName = $(this).data("filter"), filterVal = $(this).val(); if (filterVal == "") { delete filtersObject[filterName]; } else { filtersObject[filterName] = filterVal; } var filters = ""; for (var key in filtersObject) { if (filtersObject.hasOwnProperty(key)) { filters += "[data-"+key+"='"+filtersObject[key]+"']"; } } if (filters == "") { $(".listItem").show(); } else { $(".listItem").hide(); $(".listItem").hide().filter(filters).show(); } });
But for some reason it hides all the items and nothing change after changing the options
I want to initially load all the items and then filter based on the option
I want the select element to dynamically create the options with the values of the category names like the first option should have the value of cars1 and display all the other objects with the same category_name.
Note: The entire code is wrapped inside an async function which renders on page load.
Here is a proper working js fiddle with the above problem
Advertisement
Answer
Based on your fiddle code, it would be better to filter the <a>
items within the listItem
area based on season, as that is the filter that is built, instead of trying to show/hide the entire listItem
area.
The two minor code changes to achieve the desired result, is at these two code points:
Add a
data-season
reference here, to the<a>
tags, with thecategory_name
value:listItems += '<a data-season="' + category_name + '" ' + "onclick='createAVideoContainer(" + i + ")'><div class='listItem'><p>" + title + "</p></div></a>";
Change the filtering to filter on the
<a>
tags for thedata-season
that you build:if (filters == "") { $("a").show(); } else { $("a").hide(); $("a").filter(filters).show(); }
Integrating those two changes into your fiddle example code, try the runnable example below:
var data = [ { "category_name": "1", "title": "One One", "more": [ { "details": "some details" } ] }, { "category_name": "1", "title": "One Two", "more": [ { "details": "some details" } ] }, { "category_name": "2", "title": "Two One", "more": [ { "details": "some details" } ] }, { "category_name": "3", "title": "Three One", "more": [ { "details": "some details" } ] }, ]; let listItems = "", categoryAll = ""; for(var i = 0; i < data.length; i++) { var title = data[i].title, category_name = data[i].category_name; listItems += '<a data-season="' + category_name + '"' + "onclick='createAVideoContainer(" + i + ")'><div class='listItem'><p>" + title + "</p></div></a>"; if (categoryAll.indexOf("<option value='" + category_name + "'>" + category_name + "</option>") == -1) { categoryAll += "<option value='" + category_name + "'>" + category_name + "</option>"; } } $("#listitem").html(listItems); $(".filter_category_name").append(categoryAll); var filtersObject = {}; //on filter change $(".filter").on("change",function() { var filterName = $(this).data("filter"), filterVal = $(this).val(); if (filterVal == "") { delete filtersObject[filterName]; } else { filtersObject[filterName] = filterVal; } var filters = ""; for (var key in filtersObject) { if (filtersObject.hasOwnProperty(key)) { filters += "[data-"+key+"='"+filtersObject[key]+"']"; } } if (filters == "") { $("a").show(); } else { $("a").hide(); $("a").filter(filters).show(); } });
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KyZXEAg3QhqLMpG8r+8fhAXLRk2vvoC2f3B09zVXn8CA5QIVfZOJ3BCsw2P0p/We" crossorigin="anonymous"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> <div class="container"> <select data-filter="season" class="filter_category_name filter form-control"></select> <div class="listContent" id="listitem"> </div> </div> <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.3/dist/umd/popper.min.js" integrity="sha384-eMNCOe7tC1doHpGoWe/6oMVemdAVTMs2xqW4mwXrXsW0L84Iytr2wi5v2QjrP/xp" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/js/bootstrap.min.js" integrity="sha384-cn7l7gDp0eyniUwwAZgrzD06kc/tftFf19TOAs2zVinnD/C7E91j9yyk5//jjpt/" crossorigin="anonymous"></script>
Here’s the updated fiddle with the same change applied.