7

This is my demo code:

//Imports and decorators up here for Angular 2

export class ProductsListComponent {

  products = [
    { name: "A", color: "Blue", size: 50 },
    { name: "B", color: "Blue", size: 60 },
    { name: "C", color: "Black", size: 70 }
  ];

  filters = {
    colors: ["Blue", "Black"],
    sizes: [70, 50]
  };

  //This is my first approach but just works for the colors array inside filters object  
  //and i have no ideia how to filter sizes too
  filterProducts() {
    let results = [];
    this.filters.colors.forEach((color) => {
      this.products.filter((product) => {
        if (product.color === color) {
          results.push(product);
        }
        return true; //filter callback requires a boolean
      })
    });
    console.log(results);
  }

}

I would like the results array would look like this according to filters:

var results = [
  { "name": "A", "color": "Blue", "size": 50 },
  { "name": "C", "color": "Black", "size": 70 }
];

I hope to have explained my problem well.

3 Answers 3

3

here's an example using every and some array methods:

var products=[
    {"name":"A","color":"Blue","size":50},
    {"name":"B","color":"Blue","size":60},
    {"name":"C","color":"Black","size":70}
    ];

var filters={
    color:["Blue","Black"],
    size:[70,50]
    };
var r = products.filter(x =>
        Object.keys(filters).every(f => 
        filters[f].some( z => z == x[f] )))

console.log(r)

Sign up to request clarification or add additional context in comments.

Comments

2

You could rewrite function to following

filterProducts(){
    let results=[], filersCopy = angular.copy(this.filters.colors);
    this.products.filter((product)=>{
       //checking in filters.colors collection using indexOf
       let index = filersCopy.indexOf(product.color);
       if(index > -1){
          //removing matched element from copy, to ensure single occurence
          filersCopy.splice(index, 1); 
          results.push(product);
          return true;
       }
    });
    console.log(results); //Printing filtered results
}

Comments

2

I recommend to rename the filters properties same as the products properties, because this way you can implement a function that validates all filters criteria dynamically.

export class ProductsListComponent {

  products = [
    { name: "A", color: "Blue", size: 50 },
    { name: "B", color: "Blue", size: 60 },
    { name: "C", color: "Black", size: 70 }
  ];

  filters = {
    color: ["Blue", "Black"], //renamed
    size: [70, 50] //renamed
  };

  filterProducts() {
    let filterKeys = Object.keys(this.filters);
    // filters all elements passing the criteria
    return this.products.filter((item) => {
      // validates all filters criteria dynamically
      return filterKeys.every((key) => {
        // e.g. filters[color].indexOf(item[color])
        return (this.filters[key].indexOf(item[key]) !== -1);
      });
    });
  }

}

You can run the following test:

var products = [
    { name: "A", color: "Blue", size: 50 },
    { name: "B", color: "Blue", size: 60 },
    { name: "C", color: "Black", size: 70 }
  ];

var filters = {
  color: ["Blue", "Black"],
  size: [70, 50]
};

function filterProducts() {
  let filterKeys = Object.keys(filters);
  return products.filter((item) => {
    return filterKeys.every((key) => {
      return (filters[key].indexOf(item[key]) !== -1);
    });
  });
}

var filtered = filterProducts();
console.log(filtered);

1 Comment

I believe this would be the best answer for this question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.