I have an array of objects that are being used to populate an MUI table.
The objects are structured as so:
[ {
"Id": 1111,
"properties": {
"D": 0,
"A": -1,
"L": 4
}
},
{
"Id": 2222,
"properties": {
"D": 0,
"A": -1,
"L": 4
}
},
{
"Id": 3333,
"properties": {
"D": 1,
"A": -1,
"L": 4
}
},
{
"Id": 44444,
"properties": {
"D": 1,
"A": -1,
"L": 4
}
}]
Each object represents a row in the table.
My table has two MUI Selects that have multiple checkboxes that can filter a table.
Select A contains multiple check boxes: option1, option2, option3
Select B contains multiple check boxes: optionA, optionB, optionC, optionD
The table can be filtered on properties “D” and “A” From Select A. The table can also be filtered by on property “L” from Select B.
In order for a user to filter, they would open a select and choose the options they want to filter by then click “Apply” to run the filtering. If they wanted to further filter either by the same select or the other select they would then have to open which ever and choose the options thy want and hit “Apply” to run the filtering again.
In Select A the options correlate to:
const SelectA = {
option1: {
id: "option1",
name: 'Option 1',
enabled: false,
filterType: 'A',
filterId: [2, 3]
},
option2: {
id: "option2",
name: 'Option 2',
enabled: false,
filterType: 'A',
filterId: [-1, 0, 1]
},
option3: {
id: "option3",
name: 'Option 3',
enabled: false,
filterType: 'D',
filterId: [0]
},
};
Unfortunately I cannot change the filterId of the above to something different.
In Select B options correlate to:
const SelectB = {
optionA: {
id: 'optionA',
name: 'Option A',
filterId: [1],
enabled: false,
filterType: 'L'
},
optionB: {
id: 'optionB',
name: 'Option B',
filterId: [2],
enabled: false,
filterType: 'L'
},
optionC: {
id: 'optionC',
name: 'Option C',
filterId: [3],
enabled: false,
filterType: 'L'
},
optionD: {
id: 'optionD',
name: 'Option D',
filterId:[4],
enabled: false,
filterType: 'L'
}
}
I am trying to accomplish a function that filters on multiple options selected.
Examples:
- A user selects option1, option2
- A user selects option1, option2, optionB
- A user selects option2, optionC, optionD
if the row doesn’t contain the combination of filters it shouldn’t return a row.
Here is the code I currently have:
const applyFilters = (data) => {
let propertyList = data
let appliedFilters = Object.values({...SelectA, ...SelectB}).filter((item) => {
return item.enabled === true
})
Object.values(appliedFilters).forEach((item) => {
console.log(`applied filters: ${JSON.stringify(item)}`)
})
let B = Object.values(SelectB).filter((item) => {
return item.enabled === true
})
let A = Object.values(SelectA).filter((item) => {
return item.enabled === true
})
if (B.length > 0 && A.length > 0) { // We are wanting to mix and match.
propertyList = data.filter((row) => {
let propertyMatch = 0
//search through and find the A properties first
for (let i = 0; i < Object.values(SelectA).length; i++) {
let appliedFilter = Object.values(SelectA)[i]
if (appliedFilter.filterType !== 'D' && row.properties['D'] === 0) {
return
}
if (row.properties[appliedFilter.filterType] && appliedFilter.filterId.some(id => id === row.properties[appliedFilter.filterType])) {
propertyMatch++;
}
}
// then find the corresponding B properties we want applied.
for (let i = 0; i < Object.values(SelectB).length; i++) {
let appliedFilter = Object.values(SelectB)[i]
if (appliedFilter.filterType !== 'D' && row.properties['D'] === 0) {
return
}
if (row.properties[appliedFilter.filterType] && appliedFilter.filterId.some(id => id === row.properties[appliedFilter.filterType])) {
propertyMatch++;
}
}
//can have possible 2 or 3 matches if "D" is selected as a property
return [2, 3].some(propertyMatch => propertyMatch === matchedFilter);
})
}
else if (B.length > 0 ) { // we are wanting singular or multiple B properties
propertyList = data.filter((row) => {
for (let i = 0; i < Object.values(SelectB).length; i++) {
let appliedFilter = Object.values(SelectB)[i]
if (appliedFilter.filterType !== 'D' && row.properties['D'] === 0) {
return
}
if(row.properties[appliedFilter.filterType] && appliedFilter.filterId.some(id => id === row.properties[appliedFilter.filterType])) {
return true
}
}
})
}
else if (A.length > 0) { // we are wanting singular or multiple A properties
propertyList = data.filter((row) => {
for (let i = 0; i < Object.values(SelectA).length; i++) {
let appliedFilter = Object.values(SelectA)[i]
if (appliedFilter.filterType !== 'D' && row.properties['D'] === 0) {
return
}
if(row.properties[appliedFilter.filterType] && appliedFilter.filterId.some(id => id === row.properties[appliedFilter.filterType])) {
return true
}
}
})
}
}
This will filter based on two or more of the same options in the same select. This will also filter on a combination.
The problems I am having, however, are:
-
If there is a combination that shouldn’t exist it still returns the rows that do exist in the combination. It shouldn’t return any.
example: option1, optionA, optionB are selected. There are no combinations of option1 and optionB but there are combinations of option1 and optionA. This will stil show rows with option1 and optionA.
-
If a user selects option3 it doesn’t show any rows including option3.
-
Is there a way to simplify this code?