I'm trying to render a reactive widget, based on a object list.
I needed that when the children of this object, has his boolean property changes, the UI should be updated.
In this scenario, my controller has a list os Sections and each section has a list of Lessons.
To better understanding, i rewriter my code making a simple example, based on what i need. I already try using .map, .forEach, and others approaches, but the children property never trigger the UI update.
GetX<LessonController>(
initState: (state) => controller.getLessonsByCourse(course.id),
builder: (_) {
return Expanded(
child: ListView.separated(
scrollDirection: Axis.vertical,
itemCount: _.sectionList.length,
itemBuilder: (BuildContext context, int index) {
return ExpansionTile(
title: Text(_.sectionList[index].title),
children: <Widget>[
for(var i = 0; i < _.sectionList[index].lessons.length; i++)
Padding(
padding: const EdgeInsets.all(8.0),
child:
Obx(() =>
GestureDetector(
child: Text((_.sectionList[index].lessons[i] as Lesson).isCompleted.toString()),
onTap: () {
(_.sectionList[index].lessons[i] as Lesson).isCompleted = !(_.sectionList[index].lessons[i]as Lesson).isCompleted;
print((_.sectionList[index].lessons[i]as Lesson).isCompleted.toString());
})
),
)
]);
},
separatorBuilder: (context, ind) => Divider(
height: 2,
color: Colors.grey[300],
),
),
);
})
Solution:
The GetX container monitores changes on the list items, so when you change a property from one of this items, the list itself doesn't change. To solved that, i change the item property, and after that i overrited it on the list.
onTap: (value) {
Section tappedSection = _.sectionList[index];
tappedSection.lessons[lessonIndex].isCompleted = value;
// This is the secret
// Making GetX detect a change on the list and rebuild UI
_.sectionList[index] = tappedSection;
}));
As far as I could tell, an observable list in Flutter GetX is not concerned with internal changes to objects in itself.
To force the UI update, I had to return the updated object to the same position in the list, in order to pretend that there was a change in the objects in the main list.
Something like that: