Reputation: 11
I am trying to make an observable list. Specifically:
Show a list with names. The list is pulled from a list of objects containing a name key and a isSelected bool key.
List<Student> students = [
Student(name: "John", isSelected: false),
Student(name: "Boris", isSelected: false),
Student(name: "Max", isSelected: false)
];
The names are displayed in a ListView.builder. Clicking on the name should set the corresponding isSelected variable to true. This all works up to this point.
I want the list to refresh so that if isSelected is set to true, the item will show in a different color.
child: Text(
students[index].name,
style: TextStyle(
color: students[index].isSelected == true
? Colors.red
: Colors.black87,
),
),
The problems I run into are:
I get the error "Improper use of GetX. You should only use GetX or Obx for the specific widget that will be updated" no matter which widget I wrap into Obx. I have not included Obx in the code below as it leads to an error.
I have read that lists are reactive but the items inside it are not and need to be made observable. I am not clear how this is done in this instance.
I paste the complete code below. Thank you for your help and apologies for asking something that's likely pretty basic.
import 'package:flutter/material.dart';
import 'package:get/get.dart';
void main() => runApp(testApp());
class Student {
String name;
bool isSelected;
Student({required this.name, required this.isSelected});
}
class Controller extends GetxController {
var students = <Student>[].obs;
}
class testApp extends StatelessWidget {
@override
List<Student> students = [
Student(name: "John", isSelected: false),
Student(name: "Boris", isSelected: false),
Student(name: "Max", isSelected: false)
];
Widget build(BuildContext context) {
final controller = Get.put(Controller());
return MaterialApp(
home: Material(
child: ListView.builder(
itemCount: students.length,
itemBuilder: (BuildContext ctxt, int index) {
return InkWell(
onTap: () {
students[index].isSelected = true;
// refresh does not work
// controller.students.refresh();
},
child: Text(
students[index].name,
style: TextStyle(
color: students[index].isSelected == true
? Colors.red
: Colors.black87,
),
),
);
}),
));
}
}
Upvotes: 0
Views: 640
Reputation: 11
The solution was to controller.students.refresh() the list. Posting the complete working code below.
import 'package:flutter/material.dart';
import 'package:get/get.dart';
void main() => runApp(testApp());
class Student {
String name;
bool isSelected;
Student({required this.name, required this.isSelected});
}
class Controller extends GetxController {
Rx<List<Student>> students = Rx<List<Student>>([
Student(name: "John", isSelected: false),
Student(name: "Boris", isSelected: false),
Student(name: "Max", isSelected: false)
]);
}
class testApp extends StatelessWidget {
@override
//
final controller = Get.put(Controller());
Widget build(BuildContext context) {
final controller = Get.put(Controller());
return MaterialApp(
home: Material(
child: Obx(
() => ListView.builder(
itemCount: controller.students.value.length,
itemBuilder: (BuildContext ctxt, int index) {
return InkWell(
onTap: () {
controller.students.value[index].isSelected = true;
controller.students.refresh();
},
child: Text(
controller.students.value[index].name,
// students[index].name,
style: TextStyle(
color: controller.students.value[index].isSelected == true
? Colors.red
: Colors.black87,
),
),
);
}),
),
));
}
}
Upvotes: 1