I have a page where it shows ListView that contains list of schools. So I load all the schools (in initState() method) when the user clicks on My Schools.
Now I want to pass the School object when user clicks on a school's in the ListView and show the edit school page.
I want to use the provider patter for this so I can pass a single school object to the edit page and once user done with edit and press back, it automatically reflects the updated school in the ListView.
I am really confused with how to pass a single object from a list to the edit page. Following is my code where I have model, provider and state classes. As I am not getting how to access the school object in the edit page I have not created it yet.
I do not want to use the constructor to pass the school object to edit.
// School model class
class SchoolModel {
String name;
double points;
}
// school provider
class SchoolProvider with ChangeNotifier {
School _school;
School get school => _school;
set School(School value) {
_school = value;
notifyListeners();
}
}
// School list page
class ListSchool extends StatefulWidget {
@override
_ListSchoolState createState() => _ListSchoolState();
}
// List page state
class _ListSchoolState extends State<ListSchool> {
List<School> _schools;
@override
void initState() {
_schools = FirebaseCall(); // loading schools
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: MultiProvider(
providers: [
ChangeNotifierProvider(
create: (context) => SchoolProvider(),
),
],
child: ListView.builder(
itemCount: _schools.length,
itemBuilder: (BuildContext ctxt, int index) {
return ListTile(
title: Text(_schools[index].name);
onTap() {
// Open Edit page and pass the clicked school object to edit page
}
);
}
)
)
);
Thank you
I think you need to change your change notifier, to be the list that you want to update.
class SchoolsProvider with ChangeNotifier {
List<School> _schools;
School get schools => _schools;
SchoolProvider(this._schools = const []);
void addSchool(School newSchool) {
_schools.add(newSchool);
notifyListeners();
}
void removeShool(String schoolName) {
_schools.removeWhere((s) => s.name == schoolName);
notifyListeners();
}
void updateSchool(String shoolName, double points) {
_schools.removeWhere((s) => s.name == schoolName);
addSchool(School(schoolName, points));
}
}
When you tap on the ListTile you just push the new page, and pass in the desired school.
Consumer<SchoolsProvider>(
builder: (_, schools, __) => ListView.builder(
itemCount: schools.length,
itemBuilder: (BuildContext ctxt, int index) {
return ListTile(
title: Text(schools[index].name),
onTap() {
Navigator.push(context, MaterialRoutePage(
context,
builder: (_) => YourNewPage(school: schools[index]),
));
},
);
},
),
),
From the new page, you can just access the methods declared in the Provider, this will update the listeners
class NewPage extends StatelessWidget {
final School school;
NewPage({this.school});
...
//Here you can perform any action on the schools Provider
// It will notify it's listeners (Consumer) so it gets updated
schools[index].add
schools[index].remove
schools[index].update
...