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?
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
class:
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,
);
}
}
CodePudding user response:
The actual problem is that you are using the same boolean value
for all the check boxes' state(true/false[weather its selected or not]).
So, when you click on one checkbox it sets the value of value
(variable) to true and therefore all the checkboxes read the value from the common value
(which becomes true).Therefore,every box gets selected.
Solution : You may use different variables for different check boxes' state(true/false) if the number of checkboxes is limited,otherwise go for a differnet approach.
CodePudding user response:
You are getting the whole class when you call provider. In addition, value is a global variable for the class itself, not for the items inside taskList. So if you need to modify a Task individually you can do something like this:
class Tasks extends ChangeNotifier {
bool value = false;
List<Task> taskList = [
Task('Buy Milk'),
];
void addTask(Task newTask) {
taskList.add(newTask);
notifyListeners();
}
void deltaValue(bool b, int index) {
taskList[index].value = !taskList[index].value; // Individual task value
notifyListeners();
}
}
Instead of using a List of String you can create a new class called Task to store the values:
class Task extends ChangeNotifier {
String name;
bool value = false;
Task(this.name);
}
The last step would be to use a Widget that displays all the values stored on the List. For example you can use ListView.builder, so you have the index and you can use it to modify the individual value of a Task:
class TaskTile extends StatelessWidget {
String? listText;
TaskTile({this.listText, Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final tasks = Provider.of<Tasks>(context, listen: false);
final taskList = tasks.taskList; //ListView helps you iterate over all the elements on the list
return ListView.builder(
itemCount: taskList.length,
itemBuilder: (context, index) {
final task = taskList[index];
return CheckboxListTile(
title: Text(
listText!,
style: TextStyle(
decoration: task.value
? TextDecoration.lineThrough
: null,
),
),
activeColor: Colors.black,
value: task.value,
onChanged: (newValue) {
Provider.of<Tasks>(context, listen: false)
.deltaValue(newValue!,index); //Problem Here.
},
);
});
}
}