devinbost
devinbost

Reputation: 5104

Dart - filtering list of objects behaves unexpectedly... somehow all the objects contain a string

I'm getting very strange behavior when attempting to filter a list. This caught me off guard because I've done this countless times in other languages and never seen this behavior before.

I have a ProductsRepository that's returning a List<Product>. I just want to filter the objects to only those that have a product name that contains my search term. But, when I apply the filter, it's as if no filter was applied at all.

  List<Product> getFilteredProducts(String searchTerm){
    print('getting filtered products');
    List<Product> products = ProductsRepository.loadProducts(Category.all);
    print('Search term used: ' + searchTerm);
    List<Product> filteredProducts = products.where((product) => (product.name.contains(searchText))).toList();
    print(filteredProducts.map((prod) => prod.name));
    print(products.map((prod) => prod.name.contains(searchText))); // sanity check
    return filteredProducts;
  }

To my complete and utter astonishment, here is what is logged to the console:

I/flutter ( 8401): getting filtered products  
I/flutter ( 8401): Search term used: Stella  
I/flutter ( 8401): (Vagabond sack, Stella sunglasses, Whitney belt, ..., Sunshirt dress, Fine lines tee)  
I/flutter ( 8401): (true, true, true, true, true, true, true, true, true, true, ..., true, true)

How is it possible that all of these products (shown below) return true on the condition (prod) => prod.name.contains(searchText)? I also tried using (prod) => prod.name.startsWith(searchText) and got the same behavior. Could this be a bug?

For what it's worth, the getFilteredProducts method is located in a StatelessWidget in Flutter.

class ProductsRepository {
  static List<Product> loadProducts(Category category) {
    List<Product> allProducts = <Product> [
      Product(
        category: Category.accessories,
        id: 0,
        isFeatured: true,
        name: 'Vagabond sack',
        price: 120,
      ),
      Product(
        category: Category.accessories,
        id: 1,
        isFeatured: true,
        name: 'Stella sunglasses',
        price: 58,
      ),
      Product(
        category: Category.accessories,
        id: 2,
        isFeatured: false,
        name: 'Whitney belt',
        price: 35,
      ),
      Product(
        category: Category.accessories,
        id: 3,
        isFeatured: true,
        name: 'Garden strand',
        price: 98,
      ),
      Product(
        category: Category.accessories,
        id: 4,
        isFeatured: false,
        name: 'Strut earrings',
        price: 34,
      ),
      Product(
        category: Category.accessories,
        id: 5,
        isFeatured: false,
        name: 'Varsity socks',
        price: 12,
      ),
      Product(
        category: Category.accessories,
        id: 6,
        isFeatured: false,
        name: 'Weave keyring',
        price: 16,
      ),
      Product(
        category: Category.clothing,
        id: 36,
        isFeatured: false,
        name: 'Sunshirt dress',
        price: 58,
      ),
      Product(
        category: Category.clothing,
        id: 37,
        isFeatured: true,
        name: 'Fine lines tee',
        price: 58,
      ),
    ];
    if (category == Category.all) {
      return allProducts;
    } else {
      return allProducts.where((Product p) {
        return p.category == category;
      }).toList();
    }
  }
}

Here are my dependencies:

environment:
  sdk: ">=2.7.0 <3.0.0"

dependencies:
  flutter:
    sdk: flutter
  intl: ^0.15.6

  cupertino_icons: ^0.1.0
  shrine_images: 1.1.1
  provider: ^4.0.0

Upvotes: 0

Views: 171

Answers (1)

YoBo
YoBo

Reputation: 2549

You are passing serchTerms but using searchText for filtering.

Try this:

List<Product> getFilteredProducts(String searchTerm){
    print('getting filtered products');
    List<Product> products = ProductsRepository.loadProducts(Category.all);
    print('Search term used: ' + searchTerm);
    List<Product> filteredProducts = products.where((product) => (product.name.contains(searchTerm))).toList();
    print(filteredProducts.map((prod) => prod.name));
    print(products.map((prod) => prod.name.contains(searchTerm))); // sanity check
    return filteredProducts;
  }

Upvotes: 1

Related Questions