fluttermobxblocobservablelistrxdart

Mobx Observer not working on a ObservableList item


I'm trying to check and uncheck the itens in my list, but i can't change the state of the checkbox, it's just change when i add another item in the list. if i add the setState method in CheckBox Onchanged method it works.

i tried some stuff but nothing changed

code to help:

Store:

import 'package:mobx/mobx.dart';
import 'package:mobxlearn/TodoApp/models/todo.model.dart';
part 'todo.store.g.dart';

class TodoStore = _TodoStoreBase with _$TodoStore;

abstract class _TodoStoreBase with Store {

  @observable
  var todoList = ObservableList<TodoItem>();

   @action
   void addTask(TodoItem task){
     todoList.add(task);
   }

}

TodoItem:

import 'package:mobx/mobx.dart';
part 'todo.model.g.dart';

class TodoItem = _TodoItemBase with _$TodoItem;

abstract class _TodoItemBase with Store {

  @observable
  String title;

  @observable
  bool checked;

  @action
  void check(bool checkValue){
    print("item checkado - $checkValue");
    checked = checkValue;
  }


}

View:

import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:mobxlearn/TodoApp/models/todo.model.dart';
import 'package:mobxlearn/TodoApp/stores/todo.store.dart';

class TodoHome extends StatelessWidget {
  final todo = TodoStore();

  final todoController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Container(
        child: Column(
      children: <Widget>[
        Padding(
          padding: const EdgeInsets.all(8.0),
          child: Row(
            children: <Widget>[
              Expanded(
                child: TextField(
                  controller: todoController,
                  decoration: InputDecoration(
                    enabledBorder: OutlineInputBorder(),
                    focusedBorder: OutlineInputBorder(),
                    focusColor: Colors.purple,
                  ),
                  style: TextStyle(fontSize: 18, color: Colors.black),
                ),
              ),
              VerticalDivider(),
              MaterialButton(
                color: Colors.purple,
                child: Text(
                  "Add Task",
                  style: TextStyle(color: Colors.white),
                ),
                onPressed: () {
                  if (todoController.text.isNotEmpty) {
                    final todoItem = TodoItem();
                    todoItem.title = todoController.text;
                    todoItem.checked = true;
                    todo.addTask(todoItem);
                    todoController.text = "";
                    print(todo.todoList.toString());
                  }
                },
              )
            ],
          ),
        ),
        Divider(),
        Expanded(
          child: Observer(
            builder: (_) => ListView.builder(
                itemCount: todo.todoList.length,
                itemBuilder: (context, index) {
                  return ListTile(
                    leading: Checkbox(
                        value: todo.todoList[index].checked,
                        onChanged: (boolean) {
                          print(boolean);
                          todo.todoList[index].check(boolean);
                        }),
                    title: Text(todo.todoList[index].title),
                    onTap: () {},
                  );
                }),
          ),
        )
      ],
    ));
  }
}

thanks!!!!


Solution

  • So after watching a video I got the solution when we use an Observablelist and we want to change the items state of this list, we can't just create an observer to the list, we need to create an observer for each Item and for the list too:

    I needed to create a custom item and set an observer to this:

    class CustomItem extends StatelessWidget {
      final TodoItem item;
      CustomItem({this.item});
    
      @override
      Widget build(BuildContext context) {
        return Observer(
          builder: (_) {
            return ListTile(
              leading: Checkbox(value: item.checked, onChanged: item.setCheck),
              title: Text(item.title),
            );
          },
        );
      }
    }
    

    and in my view, I needed to set an observer to the list too:

    Expanded(
              child: Observer(
              builder: (_) {
                return ListView.builder(
                    itemCount: controller.list.length,
                    itemBuilder: (context, index) {
                      var item = controller.list[index];
                      return CustomItem(item: item);
                    });
              },
            ))