I have a simple thing to achieve. I have 2 screens in my app, on the main screen i have a button which navigates me to a new page called Interests. The Interests page is a list of checkboxes(for which i have to use listview.builder only) and a button to submit the data(which navigates me back to the main screen). The thing i want to achieve is this:
Any help would be appreciated!!
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(),
debugShowCheckedModeBanner: false,
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: Center(
child: RaisedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Interests(),
),
);
},
child: Text("Click here!!"),
),
),
),
);
}
}
class Interests extends StatefulWidget {
final List<dynamic> selectedList;
final void Function(List<dynamic>) callback;
Interests(this.selectedList, this.callback);
@override
_InterestsState createState() => _InterestsState();
}
class _InterestsState extends State<Interests> {
Map<String, dynamic> _categories = {
"responseCode": "1",
"responseText": "List categories.",
"responseBody": [
{"category_id": "1", "category_name": "Movies"},
{"category_id": "2", "category_name": "Sports"},
{"category_id": "3", "category_name": "Food"},
{"category_id": "4", "category_name": "Music"},
{"category_id": "5", "category_name": "Others"},
],
"responseTotalResult": 5
};
void _onCategorySelected(bool selected, categoryName) {
if (selected == true) {
setState(() {
widget.selectedList.add(categoryName);
});
} else {
setState(() {
widget.selectedList.remove(categoryName);
});
}
widget.callback(widget.selectedList);
}
applyInterestChanges() { //function to save the changes in database.
Firestore.instance
.collection('my_users')
.document(currentUserModel.id)
.updateData({
"interests": widget.selectedList,
});
} //this code is working properly. Need to similar function to retrieve the data and display the updated interests list.
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Interests"),
),
body: SingleChildScrollView(
child: Column(
children: [
Text(
"Select your interests: ",
style: TextStyle(fontSize: 20.0, fontWeight: FontWeight.bold),
),
ListView.builder(
physics: NeverScrollableScrollPhysics(),
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: _categories['responseTotalResult'],
itemBuilder: (BuildContext context, int index) {
return CheckboxListTile(
controlAffinity: ListTileControlAffinity.leading,
value: widget.selectedList.contains(
_categories['responseBody'][index]['category_name']),
onChanged: (bool selected) {
_onCategorySelected(selected,
_categories['responseBody'][index]['category_name']);
},
title:
Text(_categories['responseBody'][index]['category_name']),
);
},
),
MaterialButton(
onPressed: () {
Navigator.pop(context);
applyInterestChanges();
},
child: Text("Submit"),
),
],
),
),
);
}
}
You can pass an empty list from the parent widget MyHomeWidget & update this list via callback from the Interests widget.
Next time, whenever you go back & navigate again to Interests widget, we will pass this updated list which saves the state of Interests widget. Hence, the checkboxes will be checked depending upon their values in the list.
Here is the implementation:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(),
debugShowCheckedModeBanner: false,
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<dynamic> selectedList = [];
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: Center(
child: RaisedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Interests(
selectedList,
(List<dynamic> updatedList) {
setState(() {
selectedList = updatedList;
});
}
),
),
);
},
child: Text("Click here!!"),
),
),
),
);
}
}
class Interests extends StatefulWidget {
Interests(this.selectedList, this.callback);
// Passing the list from parent widget i.e, MyHomeWidget
// Initially the list will be empty
// We will update the list in parent whenever checkboxes change
final List<dynamic> selectedList;
// Creating a callback function to save state(update list) in
// MyHomeWidget
final void Function(List<dynamic>) callback;
@override
_InterestsState createState() => _InterestsState();
}
class _InterestsState extends State<Interests> {
Map<String, dynamic> _categories = {
"responseCode": "1",
"responseText": "List categories.",
"responseBody": [
{"category_id": "1", "category_name": "Movies"},
{"category_id": "2", "category_name": "Sports"},
{"category_id": "3", "category_name": "Food"},
{"category_id": "4", "category_name": "Music"},
{"category_id": "5", "category_name": "Others"},
],
"responseTotalResult": 5
};
void _onCategorySelected(bool selected, categoryId) {
if (selected == true) {
setState(() {
widget.selectedList.add(categoryId);
});
} else {
setState(() {
widget.selectedList.remove(categoryId);
});
}
// Callback to save the updated selectedList to MyHomeWidget list
widget.callback(widget.selectedList);
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Interests"),
),
body: SingleChildScrollView(
child: Column(
children: [
Text(
"Select your interests: ",
style: TextStyle(fontSize: 20.0, fontWeight: FontWeight.bold),
),
ListView.builder(
physics: NeverScrollableScrollPhysics(),
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: _categories['responseTotalResult'],
itemBuilder: (BuildContext context, int index) {
return CheckboxListTile(
value: widget.selectedList.contains(
_categories['responseBody'][index]['category_id']),
onChanged: (bool selected) {
_onCategorySelected(selected,
_categories['responseBody'][index]['category_id']);
},
title:
Text(_categories['responseBody'][index]['category_name']),
);
},
),
RaisedButton(
onPressed: () {
Navigator.pop(context);
},
child: Text("Go back!!"),
),
],
),
),
);
}
}
Here is the method that you wanted to fetch from Firebase. I have used the updated class FirebaseFirestore. If you are using the older version of Firebase, then simply replace FirebaseFirestore with Firebase.
Future<void> fetchInterestChanges() async { //function to get the changes in database.
final DocumentSnapshot doc = await FirebaseFirestore.instance
.collection('my_users')
.document(currentUserModel.id)
.get();
final updatedList = doc.data();
print(updatedList);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With