'How to observe ObservableList item properties changes

I'm building a shopping app in Flutter using MVC pattern and mobx for app state management.

At the moment, I have a mobx store for cart items and one store for the cart controller.

The cart controller has a ObservableList of cart items and problem is that I don't know if there's a way of observing changes on cart items.

For instance, I'd like to observe cartItem.title or cartItem.total.

Is there a way to track this with ObservableList? And whats is .observe() method the observable list has? (Think the documentation wasn't clear for me)

UPDATE: SAMPLE CODE

As I said I have to mobx sotres, one for the cart item and for the cart itself.

In the cart item store:


import 'package:mobx/mobx.dart';

part 'cart-item.model.g.dart';

class CartItemModel = _CartItemModel with _$CartItemModel;

abstract class _CartItemModel with Store {
  int id;
  String title;
  String price;
  String description;

  @observable
  int _quantity = 0;

  @observable
  double _total = 0;

  _CartItemModel({
    this.id,
    this.title,
    this.price,
    this.description,
  }) {
    reaction(
      (_) => _quantity,
      (quantity) {
        getTotal();
      },
    );
  }

  getItemQuantity() => _quantity.toString(); // Return item quantity

  @action
  increase() {
    // Increase item quantity
    if (_quantity <= 99) {
      _quantity++;
    }
  }

  @action
  decrease() {
    // Decrease item quantity
    if (_quantity > 0) {
      _quantity--;
    }
  }

  @action
  getTotal() {
    // Return total price by item quantity
    _total = double.parse(price) * _quantity;
    return _total.toString();
  }
}

And then in the cart controller:


import 'package:faccioo_user_app/models/cart-item.model.dart';
import 'package:mobx/mobx.dart';

part 'cart.controller.g.dart';

class CartController = _CartController with _$CartController;

abstract class _CartController with Store {

@observable
  ObservableList<CartItemModel> cartItems = ObservableList<CartItemModel>();

  @action
  addItem(CartItemModel item) {
    cartItems.insert(0, (item));
    item.increase();
  }

  @action
  removeItem(CartItemModel item) {
    cartItems.removeWhere((cartItem) => cartItem.id == item.id);
    getTotal();
  }

  @action
  getSubtotal() {
    cartItems.forEach((item) {
      subtotal = subtotal + double.parse(item.getTotal());
    });
    return subtotal.toString();
  }

  @action
  getTotal() {
    total = (subtotal + shippingFee + serviceFee + change) - discount;
    return total.toString();
  }

}

The view is not being notified by the changes in cartItem.total, for example?. How do I observe changes in cartItemModel.total from ObservableLis?

To be more clear I got this print in which we can see that cart item quantity and total increase, therefore CartItemModel reactivity is working fine, but the cart controller can't track those changes from ObservableList, then the controller is not updating the view.

I'd really appreciate links and references from where I can learn more about mobx with Flutter and observable lists.

Cart view with cart item



Solution 1:[1]

this is an old question but I will share the hints for the solution and how to improve it.

You don't need to create a store for the model, just wrap the properties with @observable, @computed, etc.

Actions are meant to write to the store and update the store properties. If you want to read properties, just write a simple get property without the @action annotation, or if you want to read a property based on other @observable properties, use the get with @computed.

The store should be only the CartController in which you should have a @computed property that will change based on other properties changes, e.g. for the CartController store:

The CartItemModel should be transformed into a simple data class with getters and setters and is the store that will manage its state.

I didn't check in terms of types .. etc.., the getters are missing the return types, only the setters that don't need return type.

@computed
double get total() =>  subtotal + shippingFee + serviceFee + change - discount;

@computed
  double get subtotal() {
    double subTotalAggregator = 0;
    cartItems.forEach((item) {
      subTotalAggregator += double.parse(item.getTotal());
    });
        return subTotalAggregator;
      }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 fpatelm