2

I am creating a component in my app that lists all products being sold. I am then creating a filtering component where the user can open a modal with many checkboxes. They select the different options they want to filter by, and the list of products automatically updates.

Each item that is selected goes into a new array called 'selected items', which is automatically updated each time a checkbox is clicked.

Currently, I have the ability to create a single static filter like:

var A = products.filter(e => e.categories.find(category => category.slug === "movies"));

function showA() {
  setfilteredProducts(A)
}

or with two parameters like:

var B = products.filter(e => e.categories.find(category => category.slug === "movies") && e.categories.find(category => category.slug === "books"));

function showB() {
  setfilteredProducts(B)
}

But I am looking for a way to modify the filter function so that it will filter based on all items that are selected. So instead of writing e.categories.find(category => category.slug === "movies") && e.categories.find(category => category.slug === "books") like in the var B, it would loop through my array of selected items and create e.categories.find(category => category.slug === "movies") && as many times as needed.

I am a little bit confused on how to get this to work. I may not be explaining it very clearly, so I can give more detail if necessary. But if it is enough info, any help would be appreciated.

Update:

the array I have that holds the list of selected items is:

const newArr = state.theme.filters.categories.flatMap(category => category.data).filter(item => item.checked);
bk___
  • 71
  • 10
  • Does this answer your question? [Check if an array contains any element of another array in JavaScript](https://stackoverflow.com/questions/16312528/check-if-an-array-contains-any-element-of-another-array-in-javascript) – Akif Oct 12 '20 at 18:11
  • @Akif no it doesnt – bk___ Oct 12 '20 at 18:15

3 Answers3

0

try this

function filterProductsHandler(products, filterOptionsArray) {
  const filteredProducts = products.filter( product => {
    checkAllCategoriesExist(product, filterOptionsArray);
  });
  setfilteredProducts(B)
}

function checkCategoryExist(product, categoryName) {
  return product.categories.find(category => category.slug === categoryName)
}  

function checkAllCategoriesExist(product, categoriesArr) {
  let isMatch = true;
  categoriesArr.forEach( category => {
    if ( !checkCategoryExist(product, category ) )
      isMatch = false) ;      
    });
  return isMatch;
}

tip: always splitting the code to small functions is making the coding easier and makes sense

ינון רחמים
  • 566
  • 1
  • 5
  • 12
0

If I understood it correctly you have a list of products that you want to filter if they have all the categories from a list you give. So in order to do so you can use the every function like so:

function filterProductsByCategories(products, categories) {
  return products.filter(p =>
    categories.every(category =>
      p.categories.map(c => c.slug).includes(category)
    )
  );
}

var Products = [{
    name: "Prod A",
    categories: [{
      slug: "movies"
    }]
  },
  {
    name: "Prod B",
    categories: [{
      slug: "books"
    }]
  },
  {
    name: "Prod C",
    categories: [{
      slug: "books"
    }, {
      slug: "movies"
    }]
  }
];

var a = filterProductsByCategories(Products, ["movies"]); // Returns Prod A, C
var b = filterProductsByCategories(Products, ["books", "movies"]); // Returns Prod C

console.log(a, b)
Saar Davidson
  • 1,312
  • 1
  • 7
  • 16
0

Using .every and .includes

var filterProductsByCategories = (products, selections) => {
  return products.filter(product => {
    var categories = product.categories.map(category => category.slug);
    return selections.every(selection => categories.includes(selection));
  })
}

var Products = [
  {name: "Prod A", categories:[{slug: "movies"}]},
  {name: "Prod B", categories:[{slug: "books"}]},
  {name: "Prod C", categories:[{slug: "books"}, {slug: "movies"}]}
];

var a = filterProductsByCategories(Products, ["movies"]); // Returns Prod A, C
var b = filterProductsByCategories(Products, ["books", "movies"]); // Returns Prod C
console.log(a,b)
Sudheer Jami
  • 697
  • 6
  • 15
  • It looks like with this option, i would still be hard-coding the categories to filter by (var b). Is there a way that this would filter by the the items in the array of selected categories? – bk___ Oct 12 '20 at 20:01
  • When you say "hard-coding the categories", are you referring to `["books", "movies"]`? These will be `newArr` isn't it? – Sudheer Jami Oct 12 '20 at 20:43