Search code examples
flutterdartflutter-provider

How to use Provider to check individual CheckboxListTiles?


The two places highlighted are the cause of the problem. In the image as shown below, after I add a task, I am not able to individually select a task, instead all the tasks that I have added get selected collectively. How do I fix this to just select the task that I click on?

enter image description here

This is the Tasks class that extends the ChangeNotifier:

class Tasks extends ChangeNotifier {
  bool value = false;
  List<String> taskList = [
    'Buy Milk',
  ];

  void addTask(String newTask) {
    taskList.add(newTask);
    notifyListeners();
  }
}

This is the updated entire tasks.dart file:

class TaskList extends StatelessWidget {
  const TaskList({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return Consumer<Tasks>(
      builder: (context, value, child) {
        return ListView.builder(
          itemCount: value.taskList.length,
          itemBuilder: (context, index) {
            return TaskTile(
              listText: value.taskList[index],
              functionCallback: (newValue) {}, //Enter Function Here.
            );
          },
        );
      },
    );
  }
}

class TaskTile extends StatelessWidget {
  String? listText;
  Function(bool?)? functionCallback;
  TaskTile({this.listText, this.functionCallback, Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return CheckboxListTile(
      title: Text(
        listText!,
        style: TextStyle(
          decoration: Provider.of<Tasks>(context, listen: false).boolValue
              ? TextDecoration.lineThrough
              : null,
        ),
      ),
      activeColor: Colors.black,
      value: Provider.of<Tasks>(context, listen: false).boolValue,
      onChanged: functionCallback,
    );
  }
}

    

Solution

  • The method I used was that I created an extra map in the Tasks class and defined a map called taskMap and used the strings defined in the taskList and the bool value to control TaskTile.

    The addTask function is used when adding tasks to the taskList elsewhere in the program, but it also adds tasks to the taskMap.

    The Tasks class:

    class Tasks extends ChangeNotifier {
      String? task;
    
      List<String> taskList = [
        'Buy Milk',
      ];
    
      Map<String, bool> taskMap = {
        'Buy Milk': false,
      };
    
      void addTask(String newTask) {
        taskList.add(newTask);
        taskMap[newTask] = false;
        notifyListeners();
      }
    
      void deltaValue(String newTask) {
        taskMap[newTask] = !taskMap[newTask]!;
        notifyListeners();
      }
    } 
    

    The entire tasks.dart file:

    import 'package:flutter/material.dart';
    import 'package:provider/provider.dart';
    import 'package:todoey_flutter/main.dart';
    
    class TaskList extends StatelessWidget {
      const TaskList({Key? key}) : super(key: key);
      @override
      Widget build(BuildContext context) {
        return Consumer<Tasks>(
          builder: (context, value, child) {
            return ListView.builder(
              itemCount: value.taskList.length,
              itemBuilder: (context, index) {
                return TaskTile(
                  listText: value.taskList[index],
                  functionCallback: (newValue) {
                    value.deltaValue(value.taskList[index]);
                  },
                );
              },
            );
          },
        );
      }
    }
    
    class TaskTile extends StatelessWidget {
      String? listText;
      Function(bool?)? functionCallback;
      TaskTile({this.listText, this.functionCallback, Key? key}) : super(key: key);
      @override
      Widget build(BuildContext context) {
        return CheckboxListTile(
          title: Text(
            listText!,
            style: TextStyle(
              decoration:
                  Provider.of<Tasks>(context, listen: false).taskMap[listText]!
                      ? TextDecoration.lineThrough
                      : null, //Bool value defined in the taskMap used.
            ),
          ),
          activeColor: Colors.black,
          value: Provider.of<Tasks>(context, listen: false).taskMap[listText], //Bool value defined in the taskMap used.
          onChanged: functionCallback,
        );
      }
    }