QGIS2web: the idea
In the past I already showed some ways of filtering a leaflet based webmap with simple Javascript and/or MaterializeCSS. This is a pretty much straightforward approach if you have static data: If you know the data model, it is easy to create the right filters and HTML elements to filter the map. Making this generic, is a bit more challenging:- Field-types are quite diverse in QGIS and need to be mapped to 4-5 main filter elements
- The filters may or may not apply to all or just a single layer, depending on the attributes each layer has
- The ranges, lists of each filter must be consolidated (remove duplicates, determine min/max values), treat of NULL
- Keep in mind cross browser functionality for date/time/datetime inputs
- Text selection list for strings (multiple options)
- Selection list for booleans
- integer slider
- double slider
- combined date/time/datetime select
QGIS2web filters: the approach for the selects
The main approach was:- get attributes of each layer
- map the field types to a select type
- determine the select entries
- create HTML elements using JS after main code of QGIS2web for each selected attribute
- add function for each filter type and apply filter selection of all filters to all layers
if filterItems[item]["type"] in ["str", "bool"]: endHTML += """ document.getElementById("menu").appendChild( document.createElement("div")); #placeholder DIV var div_{nameS} = document.createElement('div'); #This is the div which holds the select div_{nameS}.id = "div_{name}"; div_{nameS}.className= "filterselect"; document.getElementById("menu").appendChild(div_{nameS}); sel_{nameS} = document.createElement('select'); #this is the select itself sel_{nameS}.multiple = true; sel_{nameS}.id = "sel_{name}"; var {nameS}_options_str = "<option value='' unselected></option>"; sel_{nameS}.onchange = function(){{filterFunc()}}; #runs the same functio for all filters in the map """.format(name=itemName, nameS=safeName(itemName)) #safename removes unwanted strings in a attribute name for entry in filterItems[item]["values"]: #populating the select options endHTML += """ {nameS}_options_str += '<option value="{e}">{e}</option>'; """.format(e=entry, name=itemName, nameS=safeName(itemName)) endHTML += """ sel_{nameS}.innerHTML = {nameS}_options_str; div_{nameS}.appendChild(sel_{nameS}); var lab_{nameS} = document.createElement('div'); lab_{nameS}.innerHTML = '{name}'; lab_{nameS}.className = 'filterLabel'; div_{nameS}.appendChild(lab_{nameS}); """.format(name=itemName, nameS=safeName(itemName))The same code would be much easier to read and to write using HTML. But hey:

QGIS2web: dealing with the selections
The function, which is applied to all layers, gets the underlying JSON data of a layer, determine, whether the attribut is part of the properties or not and then removes entries which not meet the selected criteria (JavaScript):map.eachLayer(function(lyr){ if ("options" in lyr && "dataVar" in lyr["options"]){ features = this[lyr["options"]["dataVar"]].features.slice(0); try{ for (key in Filters){ if (Filters[key] == "str" || Filters[key] == "bool"){ var selection = []; for (option in Array.from(document.getElementById("sel_" + key).selectedOptions)){ selection.push(document.getElementById("sel_"+key).selectedOptions[option].value); } try{ if (key in features[0].properties){ for (i = features.length - 1;i >= 0; --i){ if (selection.indexOf(features[i].properties[key])<0 && selection.length>0) { features.splice(i,1); } } } } catch(err){ } } } catch(err){ } this[lyr["options"]["layerName"]].clearLayers(); this[lyr["options"]["layerName"]].addData(features); } }) }The code for other selects is quite similar and follows the same principles. Yet the result is really good at first sight:

The filter functionality is part of the latest experimental release 3.8.0 on github as well as in your plugin handler if you accept experimental plugins as well. If you see any issues in handling with data, please be so kind and drop a comment on github.
It’s really helpful to generate interactive filters right out of your plugin. Well done!
Very nice job ty!