0

I am trying to select multiple components in this Wrap.toList() but every first index I select doesn't change its colour indicating that it is selected. It is selected in the list but it doesn't show. See the 4 components I have selected.

my components

 Expanded(
              child: Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: GridView.count(
                    crossAxisCount: 2,
                    crossAxisSpacing: 10,
                    mainAxisSpacing: 10,
                    shrinkWrap: true,
                    children: cC.allCommodityList.map((order) {
                      return InkWell(
                        onTap: () {
                          setState(() {
                            selectedItems.contains(order)
                                ? selectedItems.remove(order)
                                : selectedItems.add(order);
                            commodityName = order.commodityName;
                            commodityid = order.commodityID;
                            // }
                          });
                        },
                        child: Card(
                            child: Column(
                          children: [
                            Expanded(
                                child: selectedItems.contains(order)
                                    ? SvgPicture.asset(
                                        'assets/toiletpaper.svg',
                                        color: Color.fromRGBO(0, 76, 32, 1),
                                      )
                                    : SvgPicture.asset(
                                        'assets/toiletpaper.svg',
                                      )),
                            selectedItems.contains(order)
                                ? TopBorderNoTap(
                                    listColor: [
                                        Color.fromRGBO(229, 229, 229, 1),
                                        Color.fromRGBO(0, 76, 32, 1),
                                      ],
                                    text: order.commodityName.toString(),
                                    color: Colors.white,
                                    textColor: Colors.white)
                                : TopBorderNoTap(
                                    listColor: [
                                      Color.fromRGBO(229, 229, 229, 1),
                                      Colors.white
                                    ],
                                    text: order.commodityName.toString(),
                                    textColor: Colors.black,
                                  )
                          ],
                        )),
                      );
                    }).toList(),
                  ))),

This is my model class, not the full code but it just returns from json and to json

  CommodityModel({
    this.commodityID,
    this.commodityName,
    this.commodityImage,
  });

  CommodityModel.fromJson(Map<String, dynamic> json) {
    commodityID = json['commodityID'];
    commodityName = json['commodityName'];
    commodityImage = json['commodityImage'];
  }
  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = <String, dynamic>{};
    data['commodityID'] = commodityID;
    data['commodityName'] = commodityName;
    data['commodityImage'] = commodityImage;
wuuyungwuu
  • 83
  • 13
  • Provide key to every Inkwell. Something like ValueKey(order.id). – Rahul Feb 20 '23 at 03:31
  • In case above doesn't work, does your model class have == and hashcode overridden (either by some plugin or by your code)? – Rahul Feb 20 '23 at 03:32
  • some how ` selectedItems.contains(order)` this line is not retuning true for the first element, if you can figure out that it will solve your problem – Ruchit Feb 20 '23 at 04:39
  • @Rahul the ValueKey didnt work. I dont think I have any of that, I dont have any plugin my model class. You can have at my updated post. – wuuyungwuu Feb 20 '23 at 04:52
  • @Ruchit yes, I am figuring out that part. I still couldn't fix it. – wuuyungwuu Feb 20 '23 at 04:53
  • Try overriding == and hashCode in your modal class. Or you can use equatable package for the same. `contains` works best when equality properties are implemented in class. – Rahul Feb 20 '23 at 04:55
  • @Rahul how do I implement the == and hashcode in my model class? – wuuyungwuu Feb 20 '23 at 05:01
  • Somehow the first index is selected when I do a Restart on the simulator. After that, it doesn't select at all. – wuuyungwuu Feb 20 '23 at 05:05
  • 1
    here is good resource: https://stackoverflow.com/a/22999113/16569443 – Rahul Feb 20 '23 at 05:44
  • @Rahul This works. Can you add your answer so I can mark it as solved? – wuuyungwuu Feb 21 '23 at 03:48

2 Answers2

0

You can try this approach to select & d-select model list item.

class MyNewWidget extends StatefulWidget {
  const MyNewWidget({super.key});

  @override
  State<MyNewWidget> createState() => _MyNewWidgetState();
}

class _MyNewWidgetState extends State<MyNewWidget> {
  final List<CommodityModel> allCommodityList = [
    CommodityModel(
        commodityID: 1,
        commodityName: "Toilet Paper",
        commodityImage: "commodityImage"),
    CommodityModel(
        commodityID: 2,
        commodityName: "Paper Towels",
        commodityImage: "commodityImage"),
    CommodityModel(
        commodityID: 3,
        commodityName: "Hand shop",
        commodityImage: "commodityImage"),
    CommodityModel(
        commodityID: 4,
        commodityName: "Air freshner",
        commodityImage: "commodityImage")
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Padding(
        padding: const EdgeInsets.all(8.0),
        child: GridView.builder(
            shrinkWrap: true,
            gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
              maxCrossAxisExtent: 200,
              childAspectRatio: 3 / 2,
              crossAxisSpacing: 20,
              mainAxisSpacing: 20,
            ),
            itemCount: allCommodityList.length,
            itemBuilder: (BuildContext ctx, index) {
              final order = allCommodityList[index];
              return Container(
                alignment: Alignment.center,
                child: InkWell(
                  onTap: () {
                    setState(() {
                      order.isSelected = !order.isSelected;
                    });
                  },
                  child: Card(
                      child: Column(
                    children: [
                      Expanded(
                          child: SvgPicture.asset(
                        'assets/toiletpaper.svg',
                        color: order.isSelected
                            ? const Color.fromRGBO(0, 76, 32, 1)
                            : null,
                      )),
                      Row(
                        children: [
                          Expanded(
                            child: Container(
                              color: order.isSelected
                                  ? const Color.fromRGBO(0, 76, 32, 1)
                                  : null,
                              child: Padding(
                                padding: const EdgeInsets.all(8.0),
                                child: Center(
                                    child: Text(
                                  order.commodityName ?? "",
                                  style: TextStyle(
                                      color: order.isSelected
                                          ? Colors.white
                                          : Colors.black),
                                )),
                              ),
                            ),
                          ),
                        ],
                      )
                    ],
                  )),
                ),
              );
            }),
      ),
    );
  }
}

class CommodityModel {
  int? commodityID;
  String? commodityName;
  String? commodityImage;
  bool isSelected =
      false; // Add key for selection handle. You can also handle with single orderID Array

  CommodityModel({this.commodityID, this.commodityName, this.commodityImage});

  CommodityModel.fromJson(Map<String, dynamic> json) {
    commodityID = json['commodityID'];
    commodityName = json['commodityName'];
    commodityImage = json['commodityImage'];
    isSelected = json['isSelected'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = <String, dynamic>{};
    data['commodityID'] = commodityID;
    data['commodityName'] = commodityName;
    data['commodityImage'] = commodityImage;
    data['isSelected'] = isSelected;
    return data;
  }
}

enter image description here

Vishal Zaveri
  • 1,372
  • 2
  • 5
  • 12
0

Try overriding == and hashCode in your modal class. Or you can use equatable package for the same. contains works best when equality properties are implemented in class.

here is good resource: stackoverflow.com/a/22999113/16569443

Rahul
  • 3,529
  • 1
  • 5
  • 19