skip to Main Content

So, I have a problem when remove icon is pressed. RemoveProduct is called and succesfully remove my product form list, but the setState function doesn’t refresh entyre widget as I want, and product still on the screen even it’s removed by the cartList.
The cart class contains two methods for adding and removing a product from the cart list, respectively. The AddProduct method adds the product to the list and calls notifyListeners to notify its listeners that the cart has been updated. Similarly, the RemoveProduct method removes the product from the list and calls notifyListeners to notify its listeners that the cart has been updated.

The cartPage class is a StatefulWidget that displays the cart contents. It takes an instance of the cart class as a parameter and uses it to build a ListView.builder that displays the contents of the cart

Here is the code:

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'product.dart';
import 'theme_data.dart';

class cart extends ChangeNotifier{
  List<Product> cartList=[];

  cart();

  void AddProduct(Product product)
  {
    cartList.add(product);
    notifyListeners();
  }
  void RemoveProduct(Product product)
  {
    cartList.remove(product);
    notifyListeners();
  }
}

class cartPage extends StatefulWidget {
  cart myCart;
  @override
  cartPage({required this.myCart,});

  State<cartPage> createState() => _cartPageState();
}

class _cartPageState extends State<cartPage> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text("Cos"),
        ),
        body: SingleChildScrollView(
            child:
            Container(
              height: MediaQuery.of(context).size.height,
              child: ListView.builder(
                itemCount: widget.myCart.cartList.length,
                itemBuilder: (BuildContext context, int index) {
                  final product = widget.myCart.cartList[index];
                    return cartWidget(product: widget.myCart.cartList[index], productCart: widget.myCart,);
                },
              ),
            ),
        ),
      );

  }
}

class cartWidget extends StatefulWidget {
  Product product;
  cart productCart;
  cartWidget({
    Key? key,
    required this.product,
    required this.productCart
  }) : super(key: key);

  @override
  State<cartWidget> createState() => _cartWidgetState();
}

class _cartWidgetState extends State<cartWidget> {
  var qty = ['1', '2', '3', '4'];
  late String _selectedValue=qty[0];

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.fromLTRB(10, 0, 10, 0),
      child: Container(
        margin: const EdgeInsets.fromLTRB(0, 15, 0, 0),
        padding: const EdgeInsets.fromLTRB(10, 5, 5, 5),
        decoration: BoxDecoration(
            color: Theme.of(context).scaffoldBackgroundColor,
            borderRadius: BorderRadius.circular(10),
            boxShadow: const [
              BoxShadow(
                spreadRadius: 1,
                blurRadius: 5,
                offset: Offset(0, 1), // changes position of shadow
              ),
            ]),
        child: Column(
          children: [
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: <Widget>[
                Expanded(
                  flex: 6,
                  child: Text(
                    widget.product.name,
                    style: TextStyle(
                      color: MyTheme.textColor(context),
                    ),
                  ),
                ),
                Expanded(
                    flex: 1,
                    child:  DropdownButton(
                      value: _selectedValue,
                      items: qty.map(
                              (e){
                            return DropdownMenuItem(value: e, child: Text(e, style: TextStyle(color: MyTheme.textColor(context)),),);
                          }
                      ).toList(),
                      onChanged: (val){
                        setState(() {
                          _selectedValue = val as String;

                        });
                      },
                    )
                ),
                Expanded(
                    flex: 1,
                    child: IconButton(
                        onPressed: () {
                          widget.productCart.RemoveProduct(widget.product);
                          setState(() {});
                        },
                        icon: Icon(
                          Icons.remove_circle_rounded,
                          color: MyTheme.buttonColor(context),
                        ))),
              ],
            ),
            Row(children: [
              Text(
                '${widget.product.price} lei',
                style: TextStyle(
                  color: MyTheme.buttonColor(context),
                ),
              ),
            ]),
          ],
        ),
      ),
    );
  }
}
}

2

Answers


  1. What you need to do is to consume the changenotifier with a consumer so that your view updates with changes to the notifier. I have modified your code to match.

    class cart extends ChangeNotifier {
      List<Product> cartList = [];
    
      cart();
    
      void AddProduct(Product product) {
        cartList.add(product);
        notifyListeners();
      }
    
      void RemoveProduct(Product product) {
        cartList.remove(product);
        notifyListeners();
      }
    }
    
    class cartPage extends StatefulWidget {
      cart myCart;
      @override
      cartPage({
        required this.myCart,
      });
    
      State<cartPage> createState() => _cartPageState();
    }
    
    class _cartPageState extends State<cartPage> {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text("Cos"),
          ),
          body: ChangeNotifierProvider<cart>.value(
            value: widget.myCart,
            child: Consumer<cart>(builder: (context, provider, __) {
              return SingleChildScrollView(
                child: Container(
                  height: MediaQuery.of(context).size.height,
                  child: ListView.builder(
                    itemCount: provider.cartList.length,
                    itemBuilder: (BuildContext context, int index) {
                      final product = provider.cartList[index];
                      return cartWidget(
                        product: provider.cartList[index],
                        productCart: provider,
                      );
                    },
                  ),
                ),
              );
            }),
          ),
        );
      }
    }
    
    class cartWidget extends StatefulWidget {
      Product product;
      cart productCart;
      cartWidget({Key? key, required this.product, required this.productCart})
          : super(key: key);
    
      @override
      State<cartWidget> createState() => _cartWidgetState();
    }
    
    class _cartWidgetState extends State<cartWidget> {
      var qty = ['1', '2', '3', '4'];
      late String _selectedValue = qty[0];
    
      @override
      Widget build(BuildContext context) {
        return Padding(
          padding: const EdgeInsets.fromLTRB(10, 0, 10, 0),
          child: Container(
            margin: const EdgeInsets.fromLTRB(0, 15, 0, 0),
            padding: const EdgeInsets.fromLTRB(10, 5, 5, 5),
            decoration: BoxDecoration(
                color: Theme.of(context).scaffoldBackgroundColor,
                borderRadius: BorderRadius.circular(10),
                boxShadow: const [
                  BoxShadow(
                    spreadRadius: 1,
                    blurRadius: 5,
                    offset: Offset(0, 1), // changes position of shadow
                  ),
                ]),
            child: Column(
              children: [
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: <Widget>[
                    Expanded(
                      flex: 6,
                      child: Text(
                        widget.product.name,
                      ),
                    ),
                    Expanded(
                        flex: 1,
                        child: DropdownButton(
                          value: _selectedValue,
                          items: qty.map((e) {
                            return DropdownMenuItem(
                              value: e,
                              child: Text(
                                e,
                              ),
                            );
                          }).toList(),
                          onChanged: (val) {
                            setState(() {
                              _selectedValue = val as String;
                            });
                          },
                        )),
                    Expanded(
                        flex: 1,
                        child: IconButton(
                            onPressed: () {
                              widget.productCart.RemoveProduct(widget.product);
                            },
                            icon: Icon(
                              Icons.remove_circle_rounded,
                            ))),
                  ],
                ),
                Row(children: [
                  Text(
                    '${widget.product.price} lei',
                  ),
                ]),
              ],
            ),
          ),
        );
      }
    }
    

    I have registered the changenotifier and provided it to your view while also wrapping it with a consumer so the view update on notifylisteners.

    Login or Signup to reply.
  2. I think the reason is because you are not using the required way of updating your UI with Provider. SetState will not work at that point. Use a consumer widget which will update the value under it’s widget tree.

    ...
    Consumer<cart>(
       builder: (context, data, child){
       return ListView.builder(
                    itemCount: widget.myCart.cartList.length,
                    itemBuilder: (BuildContext context, int index) {
                      final product = widget.myCart.cartList[index];
                        return cartWidget(
               product: data.cartList[index],//Replace with this
               productCart: data,//Replace with this
                  );
                    },
                  ),
       }
    )
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search