Carrito de compras: Eliminar artículos
Parte de la sección Gestión del estado del Journey de Flutter de Coddy. Lección 26 de 27.
Un comprador que añade el artículo equivocado necesita una forma de volver atrás: un botón de eliminar en cada fila del carrito.
El carrito puede contener el mismo producto dos veces, así que elimínalo por posición, no por producto. La regla anterior sigue vigente: nunca cambies state en el lugar. Haz una copia, modifica la copia y establécela como el nuevo estado:
void removeAt(int index) {
final copy = [...state];
copy.removeAt(index);
state = copy;
}Para saber la posición de cada fila, recorre la lista con un índice: for (var i = 0; i < cart.length; i++), y usa cart[i] para el producto de esa fila.
Elimina un artículo y observa cómo se actualiza el resto: la lista, el total y, de vuelta en la tienda, la insignia. Todos observan el mismo carrito.
Desafío
DifícilEn la pantalla del carrito:
- Añade un método
removeAt(int index)aCartque establezca una lista nueva sin ese elemento. - Mueve el precio de cada fila a
subtitley conviertetrailingen unIconButtonconIcons.deleteque elimine esa fila.
Pruébalo tú mismo
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
class Product {
const Product(this.name, this.price);
final String name;
final double price;
}
const products = [
Product('Apple', 0.5),
Product('Bread', 2.25),
Product('Cheese', 4),
Product('Milk', 1.2),
];
class Cart extends Notifier<List<Product>> {
@override
List<Product> build() => [];
void add(Product product) {
state = [...state, product];
}
}
final cartProvider = NotifierProvider<Cart, List<Product>>(Cart.new);
final totalProvider = Provider((ref) {
final cart = ref.watch(cartProvider);
return cart.fold(0.0, (sum, product) => sum + product.price);
});
void main() {
runApp(const ProviderScope(child: MyApp()));
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
home: ShopPage(),
);
}
}
class ShopPage extends ConsumerWidget {
const ShopPage({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final cart = ref.watch(cartProvider);
return Scaffold(
appBar: AppBar(
title: const Text('Shop'),
actions: [
IconButton(
icon: Badge(
label: Text('${cart.length}'),
isLabelVisible: cart.isNotEmpty,
child: const Icon(Icons.shopping_cart),
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const CartScreen()),
);
},
),
],
),
body: ListView(
children: [
for (final product in products)
ListTile(
title: Text(product.name),
subtitle: Text('\$${product.price.toStringAsFixed(2)}'),
trailing: IconButton(
icon: const Icon(Icons.add_shopping_cart),
onPressed: () {
ref.read(cartProvider.notifier).add(product);
},
),
),
],
),
);
}
}
class CartScreen extends ConsumerWidget {
const CartScreen({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final cart = ref.watch(cartProvider);
final total = ref.watch(totalProvider);
return Scaffold(
appBar: AppBar(title: const Text('Your cart')),
bottomNavigationBar: Padding(
padding: const EdgeInsets.all(24),
child: Text(
'Total: \$${total.toStringAsFixed(2)}',
style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
),
),
body: cart.isEmpty
? const Center(child: Text('Your cart is empty'))
: ListView(
children: [
for (final product in cart)
ListTile(
title: Text(product.name),
trailing: Text('\$${product.price.toStringAsFixed(2)}'),
),
],
),
);
}
}
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Gestión del estado
2Dart para modelos
Métodos en tus clasesGetters en tus clasesMantén un campo privadoSuma una lista con fold5Proyecto: Carrito de compras
Carrito de compras: Añadir al carritoCarrito de compras: La insigniaPractica por tu cuenta: Compilador de Flutter online