How to filtered two models with unrelated fields DART?

Viewed 101

I have two models but they don't have the common id field, but i need to filtered all items. I am using where method and as I have read in docs that this methos can help resolve my issue. But the thing is that it works only with the same id fiels in both models. What can i do if i want to filtered by uncommon fields?

I saw the solitions where other people create the helper class for both models and merge them into one array, but the thing is it should has the predifined size of two arrays, if i will try to add another item in CoffeeShop models or another item in menu it gives an error about the length of arrays.

My models:

class CoffeeShop {
  CoffeeShop({this.shopTitle, this.id});
   int id;
  final String shopTitle;

  @override
  String toString() => "CoffeeShop(shopTitle: $shopTitle)";
}

class CoffeeShopMenu {
  int sid;
  final String store;
  CoffeeShopMenu({this.shopMenuTitle, this.store, this.sid});

  final String shopMenuTitle;

  @override
  String toString() => "CoffeeShopMenu(shopMenuTitle: $shopMenuTitle)";
}

The code of the first screen:

class _ExpState extends State<Exp> {
  final List<CoffeeShop> coffeeShop = <CoffeeShop>[
    CoffeeShop(id: 1, shopTitle: 'Strarbucks'),
    CoffeeShop(id: 2,shopTitle: 'Dunkin doghnuts'),
    CoffeeShop(id: 3,shopTitle: 'Subway'),
    CoffeeShop(id: 4,shopTitle: 'MCCafe'),
    CoffeeShop(id: 5,shopTitle: 'Coffee Shop'),
  ];


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        actions: [
          IconButton(
            icon: Icon(
              Icons.search,
              color: Colors.white,
            ),
          ),
        ],
      ),
      body: ListView.builder(
          itemCount: coffeeShop.length,
          itemBuilder: (context, index) {
            return ListTile(
              title: Text(coffeeShop[index].shopTitle),
              onTap: () {
                Navigator.push(
                    context,
                    MaterialPageRoute(
                        builder: (context) => Exp1(
                          //here i want item to be filtered
                            sid: coffeeShop[index].id,
                            shopTitle: coffeeShop[index].shopTitle
                            )));
              },
            );
          }),
    );
  }

}

The code of the second screen:

class _Exp1State extends State<Exp1> {
 final List<CoffeeShop> coffeeShop = <CoffeeShop>[
    CoffeeShop(id: 1, shopTitle: 'Strarbucks'),
    CoffeeShop(id: 2,shopTitle: 'Dunkin doghnuts'),
    CoffeeShop(id: 3,shopTitle: 'Subway'),
    CoffeeShop(id: 4,shopTitle: 'MCCafe'),
    CoffeeShop(id: 5,shopTitle: 'Coffee Shop'),

  ];

  final List<CoffeeShopMenu> coffeeMenu = <CoffeeShopMenu>[

    CoffeeShopMenu(sid: 1, shopMenuTitle: 'Matcha'),
    CoffeeShopMenu(sid: 1,shopMenuTitle: 'Matcha'),
    CoffeeShopMenu(sid: 4,shopMenuTitle: 'Matcha'),
    CoffeeShopMenu(sid: 4,shopMenuTitle: 'pie'),
    CoffeeShopMenu(sid: 3,shopMenuTitle: 'sandwich'),
    CoffeeShopMenu(sid: 4,shopMenuTitle: 'croissant'),
    CoffeeShopMenu(sid: 5,shopMenuTitle: 'croissant A'),
    CoffeeShopMenu(sid: 5,shopMenuTitle: 'croissant A'),
    CoffeeShopMenu(sid: 2,shopMenuTitle: 'croissant'),
    CoffeeShopMenu(sid: 2,shopMenuTitle: 'Latte'),
    CoffeeShopMenu(sid: 4,shopMenuTitle: 'Latte'),
    CoffeeShopMenu(sid: 3,shopMenuTitle: 'Latte'),
    CoffeeShopMenu(sid: 5,shopMenuTitle: 'Latte'),
  ];


 int index;
     List<CoffeeShopMenu> get coffeeMenuTitle => coffeeMenu.where((element) => element.sid == coffeeShop[index].id).toList();
 @override
 Widget build(BuildContext context) {

   return Scaffold(
     appBar: AppBar(),
     body: ListView.builder(itemCount: coffeeMenuTitle.length,itemBuilder: (context, index){

       return ListTile(
         title: Text(coffeeMenuTitle[index].shopMenuTitle),
       );
     }),
   );
  }
}
1 Answers

From your code, I can see that everything is fine in your listing screen. But you are not using the sid value that are sent through constructor in Shop listing page.

             MaterialPageRoute(
                      builder: (context) => Exp1(
                          //Don't apply filter here for the sake of simplicity.
                          sid: coffeeShop[index].id, => This is not used
                          shopTitle: coffeeShop[index].shopTitle)));

In your detail page do the following.

Define a constructor

class Exp1 extends StatefulWidget {
final int sid;
final String shopTitle;

const Exp1({Key key, this.sid, this.shopTitle}) : super(key: key);
...
}

Inside your <State> add the following.

class _Exp1State extends State<Exp1> {
  final List<CoffeeShopMenu> coffeeMenu = <CoffeeShopMenu>[
    CoffeeShopMenu(sid: 1, shopMenuTitle: 'Matcha'),
    CoffeeShopMenu(sid: 1, shopMenuTitle: 'Matcha'),
    CoffeeShopMenu(sid: 4, shopMenuTitle: 'Matcha'),
    CoffeeShopMenu(sid: 4, shopMenuTitle: 'pie'),
    CoffeeShopMenu(sid: 3, shopMenuTitle: 'sandwich'),
    CoffeeShopMenu(sid: 4, shopMenuTitle: 'croissant'),
    CoffeeShopMenu(sid: 5, shopMenuTitle: 'croissant A'),
    CoffeeShopMenu(sid: 5, shopMenuTitle: 'croissant A'),
    CoffeeShopMenu(sid: 2, shopMenuTitle: 'croissant'),
    CoffeeShopMenu(sid: 2, shopMenuTitle: 'Latte'),
    CoffeeShopMenu(sid: 4, shopMenuTitle: 'Latte'),
    CoffeeShopMenu(sid: 3, shopMenuTitle: 'Latte'),
    CoffeeShopMenu(sid: 5, shopMenuTitle: 'Latte'),
  ];

  List<CoffeeShopMenu> filteredCoffeeMenu = [];

Filter the menu based on shop id in initState

  @override
  void initState() {
    super.initState();
    filteredCoffeeMenu =
        coffeeMenu.where((element) => element.sid == widget.sid).toList();
  }

Use the filteredCoffeeMenu in ListViewBuilder

  ListView.builder(
          itemCount: filteredCoffeeMenu.length,
          itemBuilder: (context, index) {
            return ListTile(
              title: Text(filteredCoffeeMenu[index].shopMenuTitle),
            );
          }),

EDIT : If you are getting the list from API, then use FutureBuilder to get API response and then perform filter process instead of doing that in initState Let know any queries:) Happy coding !!

Related