The idea was to create an advanced search page that would enable users to filter data as per their choice by selecting as many as five options to narrow down their search. The results would then later get displayed on a table. Having said that, a user may decide to filter by either using only a single option i.e By state, or by taking multiple options i.e By Name, By District, and By Category or as said earlier up to 5 options. However, I have no way of figuring out how this can be done. You would find screenshots followed by the code below:
A scenario where the user chooses to filter using the By State option
Scenario, where the options are chosen are multiple to narrow down the search
The code is as follows:
const AdvanceFilterScreen = () => {
const [byNameFilter, setByNameFilter] = useState(false);
const [name, setName] = useState('');
const [byDateFilter, setByDateFilter] = useState(false);
const [byCategoryFilter, setByCategoryFilter] = useState(false);
const [category, setCategory] = useState('');
const [byDistrictFilter, setByDistrictFilter] = useState(false);
const [district, setDistrict] = useState('');
const [byStateFilter, setByStateFilter] = useState(false);
const [status, setStatus] = useState('');
const [bySerialNumberFilter, setBySerialNumberFilter] = useState(false);
const [serialNumber, setSerialNumber] = useState('');
const [byIssueFilter, setbyIssueFilter] = useState(false);
const [buttonValue, setFilterButtonValue] = useState('');
//What the following methods do is set the value of setFilterButtonValue to '' so that
//the value of the current selected option turns to blank upon de-selecting them
//On-Click methods that store the values to choiceArray
const nameFilter = () => {
setByNameFilter(prev => !prev);
setFilterButtonValue('');
setName('')
}
const categoryFilter = () => {
setByCategoryFilter(prev => !prev);
setFilterButtonValue('');
setCategory('')
}
const districtFilter = () => {
setByDistrictFilter(prev => !prev);
setFilterButtonValue('');
setDistrict('')
}
const stateFilter = () => {
setByStateFilter(prev => !prev);
setFilterButtonValue('');
setStatus('')
}
const serialNumberFilter = () => {
setBySerialNumberFilter(prev => !prev);
setFilterButtonValue('');
setSerialNumber('')
}
return (
<div className="advanceFilterScreen">
<div className="navBarFilter">
<NavBar></NavBar>
</div>
<div className="chooseFilters">
<div className="chooseColumn">
<div className="caption">Choose Filters (Upto 5 filters at a time)</div>
<div className="filterOptions">
<div onClick={nameFilter}>
<div className={byNameFilter ? "nameSelectedFilter" : "byNameFilter"}>By Name</div>
</div>
<div onClick={() => setByDateFilter(prev => !prev)}>
<div className={byDateFilter ? "dateSelectedFilter" : "byDateFilter"}>By Date</div>
</div>
<div onClick={categoryFilter}>
<div className={byCategoryFilter ? "categorySelectedFilter" : "byCategoryFilter"}>By Category</div>
</div>
<div onClick={districtFilter}>
<div className={byDistrictFilter ? "districtSelectedFilter" : "byDistrictFilter"}>By District</div>
</div>
<div onClick={stateFilter}>
<div className={byStateFilter ? "stateSelectedFilter" : "byStatesFilter"}>By States</div>
</div>
<div onClick={serialNumberFilter}>
<div className={bySerialNumberFilter ? "serialNumberSelectedFilter" : "bySerialNumberFilter"}>By Serial Number</div>
</div>
<div onClick={() => setbyIssueFilter(prev => !prev)}>
<div className={byIssueFilter ? "issueSelectedFilter" : "byIssueFilter"}>By Issue</div>
</div>
</div>
</div>
</div>
<div className={(byNameFilter || byDateFilter || byCategoryFilter || byDistrictFilter || byStateFilter || bySerialNumberFilter || byIssueFilter) ? "filterDropdowns" : "noFilter"}>
<div className="filterClass">
{byNameFilter ? <div style={{ marginRight: "15px" }}>
<NameFilter setName={setName}></NameFilter>
</div> : null}
{byDateFilter ? <div style={{ marginRight: "15px" }}>Search By Date</div> : null}
{byCategoryFilter ? <div style={{ marginRight: "15px" }}>
<CategoryFilter setCategory={setCategory}></CategoryFilter>
</div> : null}
{byDistrictFilter ? <div style={{ marginRight: "15px" }}>
<DistrictFilter setDistrict={setDistrict}></DistrictFilter>
</div> : null}
{byStateFilter ? <div style={{ marginRight: "15px" }}>
<StatusFilter setStatus={setStatus}></StatusFilter>
</div> : null}
{bySerialNumberFilter ? <div style={{ marginRight: "15px" }}>
<SerialNumberFilter setSerialNumber={setSerialNumber}></SerialNumberFilter>
</div> : null}
{byIssueFilter ? <div>Search By Issue</div> : null}
</div>
<div>
<FilterSearchButton name={name} category={category} district={district} status={status} serialNumber={serialNumber} setFilterButtonValue={setFilterButtonValue}></FilterSearchButton>
</div>
</div>
<div style={{ marginTop: "50px" }}>
{district ? <DistrictTable district={district}></DistrictTable> : null}
<Table buttonValue={buttonValue}></Table>
</div>
</div>
);
};
export default AdvanceFilterScreen;
FilterSearchButton
component
This is where the filtering occurs using the props received from the selected options. Right now, this component is configured only to filter using one prop value (i.e either using the name, category, district props etc.). What should I do to filter using multiple conditions using? Just to remind you again, the selected options have been passed on as props to this component.
const FilterSearchButton = ({ name, category, district, status, serialNumber, setFilterButtonValue }) => {
const [multiFilter, setMultiFilter] = useState([]);
useEffect(() => {
setMultiFilter(dummyData.flatMap(value => value.ward_no.flatMap(
valueArray => ['grievances', 'general', 'urgent', 'services'].flatMap(
value => valueArray[value]))).filter(value => value.name === name ||
value.districtName === district ||
value.type === category ||
value.status === status ||
value.serial_number === serialNumber
)
)
}, [name, category, district, status, serialNumber, setFilterButtonValue]);
const searchFilter = () => {
setFilterButtonValue(multiFilter)
}
return (
<div className="searchFilterButton" onClick={searchFilter}>Search</div>
);
}
export default FilterSearchButton;
P.S: dummyData
is a JSON file on which the filtering occurs. The ['grievances', 'general', 'urgent', 'services']
represents the keys over which the filtering occurs. An extract of the JSON data is below. I have removed most of the properties to keep them short.
[
{
"district": "Kolkata",
"ward_no": [
{
"ward": "6",
"grievance": [
{
"serial_number": "0001",
"name" : "Mr.A"
},
{
"serial_number": "0002",
"name" : "Mr.B"
}
],
"general": [
{
"serial_number": "0003",
"name" : "Mr.C"
},
{
"serial_number": "0004",
"name" : "Mr.D"
}
]
},
{
"ward": "7",
"grievance": [
{
"serial_number": "0005",
"name" : "Mr.E"
},
{
"serial_number": "0006",
"name" : "Mr.F"
}
],
"general": [
{
"serial_number": "0007",
"name" : "Mr.G"
},
{
"serial_number": "0008",
"name" : "Mr.H"
}
]
}
]
},
{
"district": "Hooghly",
"ward_no": [
{
"ward": "8",
"grievance": [
{
"serial_number": "0009",
"name" : "Mr.I"
},
{
"serial_number": "0010",
"name" : "Mr.J"
}
],
"general": [
{
"serial_number": "0011",
"name" : "Mr.K"
},
{
"serial_number": "0012",
"name" : "Mr.L"
}
]
},
{
"ward": "9",
"grievance": [
{
"serial_number": "0013",
"name" : "Mr.M"
},
{
"serial_number": "0014",
"name" : "Mr.N"
}
],
"general": [
{
"serial_number": "0015",
"name" : "Mr.O"
},
{
"serial_number": "0018",
"name" : "Bruno Fernandes"
}
]
}
]
}
]
If the data you want to filter requires complex criteria (such as Type = "Produce" OR Salesperson = "Davolio"), you can use the Advanced Filter dialog box.
Filter Data Based on Cell Values that Contain Text Let’s assume that we have a dataset of products with their sales persons’ names, joining dates, and total sales. Now we will filter data based on the salesperson’s name. There are two additional functions used in the formula. They are ISNUMBER Click on the function’s name to learn more about them.
'Number of filters to apply numberOfFilters = InputBox ("Number of filters to apply to Column " & colNumber) Redim filters (0 to numberOfFilters - 1) As String '<-- resize according to user input Thanks for contributing an answer to Stack Overflow!
The reason is dataframe may be having multiple columns and multiple rows. Selective display of columns with limited rows is always the expected view of users. To fulfill the user’s expectations and also help in machine deep learning scenarios, filtering of Pandas dataframe with multiple conditions is much necessary.
Create Filterable DIV Elements 1 Step 1) Add HTML:#N#Example#N#<!-- Control buttons -->#N#<div id="myBtnContainer">#N#<button class="btn active"... 2 Step 2) Add CSS:#N#Example#N#.container {#N#overflow: hidden;#N#}#N#.filterDiv {#N#float: left;#N#background-color: 3 2196F3;#N#color:... 4 Step 3) Add JavaScript: More ...
This might have a performance impact if your list is really big, but since .filter()
returns back an array, why not chain 5 filters together.
For example,
let a = [1,2,3,4,5,6,7,8,9,10]
console.log(a.filter(b => b > 0).filter(c => c > 1).filter(d => d > 2).filter(e => e > 3))
This would print the array - [4,5,6,7,8,9,10]
Wrap you filter logic in a useEffect
and so whenever an input changes for the props, the useEffect can run again. Maybe you could improve it by using useCallback
as well.
I hope you get the idea and can use it for your solution
try to do a filter that you will add to him more arguments when you start to select more stuff
and then you send it a method that will do something like that
const filterHandler =(data)=>{
let flag = true;
if(bySerialNumberFilter){
flag = data?.ward_no[0]?.grievance?.serial_number === serialNumber
}
return flag;
}
in the data you pass the value from the filter and like this you do if to each of the values that the byState is true then you compare it like that you can add more search on the fly the flag is initial as true because by default you want it to be display you can put it as no but then you need to check if you dont put any filter on
const [filteredData,setFilteredData] = useState([]) //render this list
const [name, setName] = useState('');
const [status,setStatus] = useState('');
const [district, setDistrict] = useState('');
const [status, setStatus] = useState('');
const data=[......] //original data
const checkInStatus =(obj,value,key)=>{
const statusList = ['grievances', 'general', 'urgent', 'services'];
for (let status in statusList){
if(obj?.[status]?.[key] === value) return true
}
return false
}
useEffect(()=>{
//no need to use byname, bycategory etc. Just filter the based on fields that have a value. To remove a filter just set its value to ''.
let filtered = data.filter(e => district ? e.district === district:true ) //return all data if no filter by district
filetered = filtered.filter(e => {
if(!name) return true;
if(e[status] === name) return true;
return checkInStatus(e,name,'name')
})
},[name,category,district,status])
Only some filters are explained. You can use the same logic for the rest of the filters also
For status
no need to filter the data . While rendering just render only the fields for that status.
filteredData.map(e=> e[status].map(c=>c.name)}) // store status as a state
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With