0

I currently have been using mobx for my flutter app, and I'm trying to update a ListTile to change it's colour onTap. Right now I have I have an ObservableList marked with @observable, and an @action that changes a property on an item in that list.

class TestStore = TestStoreBase with _$TestStore;

abstract class TestStoreBase with Store {
  final DataService _dataService;

  TestStoreBase({
    @required DataService dataService,
  })  : assert(dataService != null),
        _dataService = dataService,
        players = ObservableList<Player>();

  @observable
  ObservableList<Player> players;

  @action
  Future<void> loadPlayers(User user) async {
    final userPlayers = await _dataService.getUserPlayers(user);
    players.addAll(userPlayers);
  }

  @action
  void selectPlayer(int index) {
    players[index].isSelected = !players[index].isSelected;
    );
  }
}

in my UI I have this inside of a listbuilder:

return Observer(builder: (_) {
    return Container(
        color: widget.testStore.players[index].isSelected != null &&
                widget.testStore.players[index].isSelected
                    ? Colors.pink
                    : Colors.transparent,
        child: ListTile(
               leading: Text(widget.testStore.players[index].id),
               onTap: () => widget.testStore.selectPlayer(index),
             ),
           );
        });

but it doesn't redraw when I call widget.testStore.selectPlayer(index);

The second thing I tried was to add @observable in the 'Players' class on the isSelected bool, but it doesn't seem to work either.

@JsonSerializable()
class Player {
  final String id;
  final bool isUser;

  @observable
  bool isSelected;

  Player(this.id, this.isUser, this.isSelected);

  factory Player.fromJson(Map<String, dynamic> data) => _$PlayerFromJson(data);

  Map<String, dynamic> toJson() => _$PlayerToJson(this);
}

any help would be greatly appreciated, thanks!

1 Answers1

1

Your are trying to take actions on the isSelected property, so basically you have to define the Player class as a MobX store as well to create a mixin that triggers reportWrite() on modifying isSelected.

Adding @observable annotation to players property only means to watch on the property itself, and typing players as a ObservableList means to watch on the list elements of the property, i.e. to watch on players[0], players[1]...and so on.

For example

@JsonSerializable()
class Player = _Player with _$Player;

abstract class _Player with Store {
  final String id;
  final bool isUser;

  @observable
  bool isSelected;

  _Player(this.id, this.isUser, this.isSelected);

  factory _Player.fromJson(Map<String, dynamic> data) => _$PlayerFromJson(data);

  Map<String, dynamic> toJson() => _$PlayerToJson(this);
}

Here is a similar issue from MobX's GitHub repo: https://github.com/mobxjs/mobx.dart/issues/129

Lance Chen
  • 586
  • 5
  • 12
  • So for this case, marking the list with extension: .asObservale() doesn't work? – MarcoFerreira Aug 20 '22 at 16:47
  • @MarcoFerreira I'm afraid not, `asObservable()` is just a sugar syntax of `ObservableList.of()`. See https://github.com/mobxjs/mobx.dart/blob/mobx-2.0.7/mobx/lib/src/api/extensions/observable_list_extension.dart. – Lance Chen Aug 21 '22 at 21:27