Balaji Kartheeswaran
Balaji Kartheeswaran

Reputation: 1098

Implement multiple filters using Flutter and Dart

I have a list lets's say 'ProductList'

I have a filter bar with tiltes 'Color' and 'Shape' with toggle buttons Red, green, square and round.

Color: Red Green

Shape: Square Round

1st category - Color

If I click red, the 'ProductList' must be filtered for Red color.

firstFilteredList = ProductList.where((p) => p.color == "red");

Now if I click green, the 'ProductList' must be filtered for Red and Green color.

firstFilteredList = ProductList.where((p) => p.color == "red" || p.color == "green");

2st category - Shape

Now if I click square, the 'firstFilteredList' must be filtered for square shape.

secondFilteredList = firstFilteredList.where((p) => p.shape == "square");

Now if I click round, the 'firstFilteredList' must be filtered for square and round shape.

secondFilteredList = firstFilteredList.where((p) => p.shape == "square" || p.shape == "round");

I need to remove those filters if the button is toggled off.

I've just mentioned two filter categories - Color and shape, for the sake of simplicity. There may be 6-7 filter categories. So, the solution has to be scalable.

Can someone help me solve this?

Edit: ProductList is a element of CategorizedProduct. I have to return List.

class CategorizedProduct {
  String id;
  String title;
  List<Product> product;
  String selectedVariant;
}

class Product {
  String color;
  String id;
  bool shapeRectangle;
  bool shapeRound;
  bool shapeSquare;
}

Upvotes: 2

Views: 5177

Answers (2)

easeccy
easeccy

Reputation: 5086

You can put your queries in a list than perform contains().

Here is a Dart example that does it.

enum ProductColor { RED, GREEN, BLUE }

enum Weight { HEAVY, NORMAL, LIGHT }

enum Shape { SQUARE, ROUND, TRIANGLE }

class Product {
  final String name;
  final ProductColor color;
  final Weight weight;
  final Shape shape;
  Product(this.name, this.color, this.weight, this.shape);
  @override
  String toString() {
    return '$name $color $weight $shape';
  }
}

class Query {
  final List<ProductColor> color;
  final List<Weight> weight;
  final List<Shape> shape;

  Query({this.color, this.weight, this.shape});
}

List<Product> filter(List<Product> products, Query query) {
  return products
      .where((product) =>
          (query.color == null || query.color.contains(product.color)) &&
          (query.weight == null || query.weight.contains(product.weight)) &&
          (query.shape == null || query.shape.contains(product.shape)))
      .toList();
}

void main() {
  List<Product> _productList = [
    Product("P1", ProductColor.BLUE, Weight.HEAVY, Shape.TRIANGLE),
    Product("P2", ProductColor.GREEN, Weight.NORMAL, Shape.ROUND),
    Product("P3", ProductColor.RED, Weight.LIGHT, Shape.ROUND),
    Product("P4", ProductColor.GREEN, Weight.NORMAL, Shape.SQUARE),
  ];

  Query _query = Query(color: [ProductColor.GREEN], shape: [Shape.ROUND]);

  List<Product> results = filter(_productList, _query);
  results.forEach(print);
}

Upvotes: 8

lenz
lenz

Reputation: 2425

You want to use a onPressed() for your filter selections, with a boolean for on or off (filter selected or not). Something like this:

//red color filter button 
...
onPressed(
  redFilter = !redFilter; //on if off, off if on...
)

Then you can use a list of boolean

bool redFilter = false; 
bool greenFilter = false;
bool squareFilter = false;
bool roundFilter = false;

List<bool> filters = [redFilter, greenFilter, squareFilter, roundFilter];

Upvotes: 0

Related Questions