skip to Main Content

There is a function, getItems, and I would like to be able to have multiple where to modify the resulting list. I am new to Dart and cannot find the syntax for passing in a where.

I tried creating functions with custom where to call getItems, but cannot due to the async nature of getItems.

  Future<List<IioMenuItem>> getItems() async {

    // ...
    final db = await openDatabase(path, readOnly: true);
    final List<Map<String, dynamic>> maps = await db.query('menu_items');

    final dbFilteredItems = maps.map((item) => IioMenuItem(
      // assign values code removed
    )).where((element) {  // <-- make 'where' replaceable
      if (filterState == FilterState.all) {
        return true;
      } else {
        return element.type.name == filterState.name;
      }
    }).toList(growable: false);

    return List.generate(dbFilteredItems.length, (i) {
      return dbFilteredItems[i];
    });
  }

The failed attempt

  Future<List<IioMenuItem>> menuItems(FilterState filterState) async {
    final dbFilteredItems = getItems().where((element) { // The method 'where' isn't defined for the type 'Future'. 
      if (filterState == FilterState.all) {
        return true;
      } else {
        return element.type.name == filterState.name;
      }
    }).toList(growable: false);

    return List.generate(dbFilteredItems.length, (i) {
      return dbFilteredItems[i];
    });
  }

Can I please get help?

3

Answers


    1. You can pass any test inside a where.
    filterItems(Map<String,dynamic> element) {
        if (filterState == FilterState.all) {
            return true;
          } else {
            return element.type.name == filterState.name;
          }
    }
    
    final dbFilteredItems = maps.map((item) => IioMenuItem(
          // assign values code removed
        )).where(filterItems).toList(growable: false);
    
    
    
    1. Use then in future
      getItems().then((value) => value.where((element ...
    Login or Signup to reply.
  1. Use await to call async functions.

    Future<List<IioMenuItem>> menuItems(FilterState filterState) async {
        final dbFilteredItems = (await getItems()).where((element) { // await has to be used here. 
          if (filterState == FilterState.all) {
            return true;
          } else {
            return element.type.name == filterState.name;
          }
        }).toList(growable: false);
        return dbFilteredItems;
      }
    
    Login or Signup to reply.
  2. The term you’re looking for is a "closure" or "first class function".

    See Functions as first-class objects on the Language guide.

    "A where" isn’t a thing. It’s not a noun. Iterable.where is just the name of a function, and that function happens to take a function as a parameter, and uses it to determine what things to keep.

    In this specific case, you want a function that takes a IioMenuItem, and returns a boolean that determins where or not to keep it. The type of that is a bool Function(IioMenuItem) (see Function).

    I called it "predicate":

    Future<List<IioMenuItem>> menuItems(
        FilterState filterState,
        bool Function(IioMenuItem) predicate // <- Take it in as a parameter
    ) async {
        return (await getItems())
            .where(predicate) // <- pass it along as an argument to `where`
            .toList(growable: false);
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search