Home > Back-end >  Flutter how to access data in the instance of an object gotten from a bloc
Flutter how to access data in the instance of an object gotten from a bloc

Time:08-18

I am trying to get the productID from the list of products in my cart bloc and then merge the list with the cart quantity so that the end result is this:

  "aos": [
    {
      "product_id": 10,
      "quantity": 1
    },
    {
      "product_id": 11,
      "quantity": 2
    }
  ],

I have tried to encode the map as a json, but there is still no option for me to access the id of each product. Please can someone point me in the right direction? My Checkout Screen:

class CheckoutScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // final List<dynamic> aos;
    return Scaffold(
        appBar: AppBar(
          backgroundColor: buttonBG,
        ),
        body: Column(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            const ShippingAddress(),
            const SizedBox(height: 20),
            BlocBuilder<CartBloc, CartState>(
              builder: (context, state) {
                if (state is CartLoaded) {
                  Map aos = state.cart.productQuantity(state.cart.products);
                  var pio = aos.keys.toList();
                  String productInstance = json.encode(pio);
                  debugPrint(productInstance);
                  return Expanded(
                    child: SizedBox(
                      height: 400,
                      child: ListView.builder(
                        itemCount: aos.keys.length,
                        itemBuilder: (BuildContext context, int index) {
                          final pIndex = aos.keys.elementAt(index);
                          final qIndex = aos.values.elementAt(index);
                          return ProductCard.summary(
                            product: pIndex,
                            quantity: qIndex,
                          );
                        },
                      ),
                    ),
                  );
                }
                return const Text('Something went wrong');
              },
            ),
          ],
        ));
  }
}

Is there a way to achieve that because i am using bloc? Below is my CartModel:

import 'package:afia4_shopping_app/logic/models/product_models.dart';
import 'package:equatable/equatable.dart';

class Cart extends Equatable {
  final List<ProductModel> products;

  const Cart({this.products = const <ProductModel>[]});

  @override
  List<Object?> get props => [products];

  Map productQuantity(products) {
    var quantity = {};

    products.forEach((product) {
      if (!quantity.containsKey(product)) {
        quantity[product] = 1;
      } else {
        quantity[product]  = 1;
      }
    });

    return quantity;
  }

}

For the cartBloc:

class CartBloc extends Bloc<CartEvent, CartState> {
  CartBloc() : super(CartLoading()) {
    on<LoadCart>(_onLoadCart);
    on<AddProduct>(_onAddProduct);
    on<RemoveProduct>(_onRemoveProduct);
  }

  void _onLoadCart(
    LoadCart event,
    Emitter<CartState> emit,
  ) async {
    emit(CartLoading());
    try {
      await Future<void>.delayed(const Duration(seconds: 1));
      emit(CartLoaded());
    } catch (_) {
      emit(CartError());
    }
  }

  void _onAddProduct(
    AddProduct event,
    Emitter<CartState> emit,
  ) {
    if (state is CartLoaded) {
      try {
        emit(
          CartLoaded(
            cart: Cart(
              products: List.from((state as CartLoaded).cart.products)
                ..add(event.product),
            ),
          ),
        );
      } on Exception {
        emit(CartError());
      }
    }
  }

  void _onRemoveProduct(
    RemoveProduct event,
    Emitter<CartState> emit,
  ) {
    if (state is CartLoaded) {
      try {
        emit(
          CartLoaded(
            cart: Cart(
              products: List.from((state as CartLoaded).cart.products)
                ..remove(event.product),
            ),
          ),
        );
      } on Exception {
        emit(CartError());
      }
    }
  }
}

For the productModel:

class ProductModel {
  ProductModel(
      {this.name,
      this.id,
  });

  String? name;
  int? id;


  factory ProductModel.fromJson(Map<String, dynamic> json) => ProductModel(
      name: json["name"],
      id: json["id"],


  Map<String, dynamic> toJson() => {
        "name": name,
        "id": id
      };

List<ProductModel> productsFromJson(String str) => List<ProductModel>.from(
    json.decode(str).map((x) => ProductModel.fromJson(x)));

String productsToJson(List<ProductModel> data) =>
    json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
}

CodePudding user response:

If you add this dependency: collection: ^1.16.0, and include that:

import "package:collection/collection.dart";

You can use the groupListsBy() method and run:

var group = cart.products.groupListsBy((element) => element.id).map((key, value) => MapEntry(key, value.length));

Which will give you a Map<int?, int> grouping product id to the quantity.

You can then present it as you wish in your UI.

  • Related