I have a shopping app, Using Provider I am able to create a list of Cart items. Based on the price and the quantity from each item, a grand total is calculated. I want the user to enter their own quantity.
Here is my CartScreen
Widget build(BuildContext context) {
final cart = Provider.of<Cart>(context);
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.red,
title: Text("Items Purchased"),
),
body: Column(
children: <Widget>[
Card(
margin: EdgeInsets.all(15),
child: Padding(
padding: EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
'Total',
style: TextStyle(
fontSize: 20,
),
),
Spacer(),
Chip(
label: Text(
'GHC ${cart.totalAmount}',
style: TextStyle(
color: Colors.white,
),
),
backgroundColor: Colors.redAccent,
),
FlatButton(
onPressed: () {
print(cart);
// Provider.of<Orders>(context).addOrder(
// cart.items.values.toList(), cart.totalAmount);
// cart.clear();
},
child: Text("CONFIRM"),
),
],
),
),
),
SizedBox(
height: 10,
),
Expanded(
child: ListView.builder(
itemCount: cart.itemCount,
itemBuilder: (ctx, i) => CartItemWidget(
cart.items.values.toList()[i].id,
cart.items.keys.toList()[i],
cart.items.values.toList()[i].price,
TextField(
controller: _controllers[i],
onChanged: (value) {
final x = double.tryParse(value);
setState(() {
itemTotal = x ?? 0;
itemTotal = cart.items.values.toList()[i].price * x;
print(itemTotal);
});
},
),
cart.items.values.toList()[i].quantity,
cart.items.values.toList()[i].title,
cart.items.values.toList()[i].image),
),
),
],
),
);
}
I think the calculation should be at the CartItemWidget
instead.
class CartItemWidget extends StatelessWidget {
final String id;
final String productId;
final double price;
final Widget quantityField;
final int quantity;
final String title;
final String image;
CartItemWidget(this.id, this.productId, this.price, this.quantityField,
this.quantity, this.title, this.image);
@override
Widget build(BuildContext context) {
return Dismissible(
key: ValueKey(id),
direction: DismissDirection.endToStart,
background: Container(
color: Theme.of(context).errorColor,
child: Icon(
Icons.delete,
color: Colors.white,
size: 40,
),
alignment: Alignment.centerRight,
padding: EdgeInsets.only(right: 20),
margin: EdgeInsets.symmetric(horizontal: 15, vertical: 4),
),
onDismissed: (direction) {
Provider.of<Cart>(context, listen: false).removeItem(productId);
},
child: Card(
margin: EdgeInsets.symmetric(
horizontal: 15,
vertical: 4,
),
child: Padding(
padding: EdgeInsets.all(8),
child: ListTile(
leading: CircleAvatar(
child: FittedBox(child: Image.asset(image)),
backgroundColor: Colors.black38,
),
title: Text(title),
subtitle: Text('Total: GHC ${(price * quantity)}'),
trailing: Container(width: 70.0, child: TextField()),
// trailing: Text('$quantity X'),
),
),
),
);
}
}
I have a Model class with Provider too.
class CartItem with ChangeNotifier {
final String id;
final String title;
final int quantity;
final double price;
final String image;
CartItem(
{@required this.id,
@required this.title,
@required this.quantity,
@required this.price,
this.image});
}
class Cart with ChangeNotifier {
Map<String, CartItem> _items = {};
Map<String, CartItem> get items {
return {..._items};
}
int get itemCount {
return _items.length;
}
double get totalAmount {
double total = 0.0;
_items.forEach((key, cartItem) {
total += cartItem.price * cartItem.quantity;
});
return total;
}
double get totalForEachItem {
double total = 0.0;
_items(key, cartItem) {
total = cartItem.price * cartItem.quantity;
}
}
void addItems(String productId, double price, String title, String image) {
if (_items.containsKey(productId)) {
//change quantity
_items.remove(productId);
// clear();
} else {
_items.putIfAbsent(
productId,
() => CartItem(
id: DateTime.now().toString(),
title: title,
price: price,
quantity: 1,
image: image),
);
}
notifyListeners();
}
void removeItem(String productId) {
_items.remove(productId);
notifyListeners();
}
void getItemTotal(String productId, double price, int quantity) {}
void clear() {
_items = {};
notifyListeners();
}
}
What I want Currently the product details such as name, price and quantity are passed from the products page. I want the user to enter their own quantity and total will automatically update by multiplying the quantity entered for cartItem[i] by the price at cartItem[i] and add the total for each item for the grandtotal.
What I have done I created a list of controllers so i can get the values at each cartitem. I also used the onChange to get the value to multiply the price and set a total with that.