im new to flutter and i wanted to know how can i retrieve a user data from firebase to my profile page?
my firebase data contain a name, email, blood type, and a date of birth. and i would like to retrieve these data to my app's profile page.
this is my profile page code
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:line_awesome_flutter/line_awesome_flutter.dart';
import '../Reminder/ui/theme.dart';
class ProfilePage extends StatefulWidget {
const ProfilePage({super.key});
#override
State<ProfilePage> createState() => _ProfilePageState();
}
class _ProfilePageState extends State<ProfilePage> {
final user = FirebaseAuth.instance.currentUser!;
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
//leading: IconButton(onPressed: (){}, icon: const Icon(Icons.arrow_back_ios_new),),
centerTitle: true,
title: Text(
'Profile',
style: headingStyle,
),
backgroundColor: Get.isDarkMode ? Colors.grey[700] : Colors.white,
),
body: SingleChildScrollView(
child: Container(
padding: const EdgeInsets.all(10),
child: Column(
children: [
SizedBox(
width: 120,
height: 120,
child: Image(image: AssetImage("images/profile.png")),
),
const SizedBox(height: 50),
Form(
child: Column(
children: [
TextFormField(
decoration: InputDecoration(
prefixIconColor: Get.isDarkMode?Colors.black:Colors.white,
focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(100), borderSide: BorderSide(color: Get.isDarkMode?Colors.white:Colors.black,)),
labelText: "Email",
prefixIcon: Icon(LineAwesomeIcons.envelope_1, color: Get.isDarkMode?Colors.white:Colors.black),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(100))),
),
SizedBox(height: 10),
TextFormField(
decoration: InputDecoration(
prefixIconColor: Get.isDarkMode?Colors.black:Colors.white,
focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(100), borderSide: BorderSide(color: Get.isDarkMode?Colors.white:Colors.black,)),
labelText: "Full Name",
prefixIcon: Icon(LineAwesomeIcons.user, color: Get.isDarkMode?Colors.white:Colors.black),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(100))),
),
SizedBox(height: 10),
TextFormField(
decoration: InputDecoration(
prefixIconColor: Get.isDarkMode?Colors.black:Colors.white,
focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(100), borderSide: BorderSide(color: Get.isDarkMode?Colors.white:Colors.black,)),
labelText: "Date of Birth",
prefixIcon: Icon(LineAwesomeIcons.baby_carriage, color: Get.isDarkMode?Colors.white:Colors.black),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(100))),
),
SizedBox(height: 10),
TextFormField(
decoration: InputDecoration(
prefixIconColor: Get.isDarkMode?Colors.black:Colors.white,
focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(100), borderSide: BorderSide(color: Get.isDarkMode?Colors.white:Colors.black,)),
labelText: "Blood Type",
prefixIcon: Icon(Icons.bloodtype, color: Get.isDarkMode?Colors.white:Colors.black),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(100))),
),
SizedBox(height: 15,),
SizedBox(
width: 100,
child: MaterialButton(
onPressed: () {
FirebaseAuth.instance.signOut();
},
color: Colors.redAccent,
child: Text('SIGN OUT'),
),
),
],
),
)
],
),
),
),
);
}
}
Use either StreamBuilder or FutureBuilder and get the data from firebase and display it accordingly
1. StreamBuilder
When you want to listen to changes constantly, and want the data to get updated without hot reload/restart
2. FutureBuilder
When you want to get the document only once and have no requirement of listening constantly to the change of the document.
Using StreamBuilder
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: StreamBuilder<DocumentSnapshot<Map<String, dynamic>>>(
stream: FirebaseFirestore
.instance
.collection('users')
.doc(FirebaseAuth.instance.currentUser!.uid) // 👈 Your document id which is equal to currentuser
.snapshots(),
builder:
(BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {
if (snapshot.hasError) {
return const Text('Something went wrong');
}
if (snapshot.connectionState == ConnectionState.waiting) {
return const Text("Loading");
}
Map<String, dynamic> data =
snapshot.data!.data()! as Map<String, dynamic>;
return Text(data['fullName']); // 👈 your valid data here
},
),
),
);
}
Using FutureBuilder
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: FutureBuilder<DocumentSnapshot<Map<String, dynamic>>>(
future: FirebaseFirestore.instance
.collection('users')
.doc(FirebaseAuth.instance.currentUser!.uid) // 👈 Your document id which is equal to currentuser
.get(),
builder: (_, snapshot) {
if (snapshot.hasError) return Text('Error = ${snapshot.error}');
if (snapshot.connectionState == ConnectionState.waiting) {
return const Text("Loading");
}
Map<String, dynamic> data = snapshot.data!.data()!;
return Text(data['fullName']); //👈 Your valid data here
},
)),
);
}
You can use stram builder to retrieve data from the firebase and display it to the user on real time. It may have some issues with styling, since I wrote it without any IDE, but I hope you'll get the idea how to get your data from stream builder.
Example:
class ProfilePage extends StatefulWidget {
const ProfilePage({super.key});
#override
State<ProfilePage> createState() => _ProfilePageState();
}
class _ProfilePageState extends State<ProfilePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children:[
StreamBuilder(
stream: FirebaseFirestore.instance
.collection('your_collection')
.snapshots(),
builder: (context,
AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) {
return Center(
child: SizedBox(
height: 50,
width: 50,
child: CircularProgressIndicator(
color: Style.blueColorDark,
backgroundColor: Style.olive,
),
),
);
}else{
return ListView(
shrinkWrap: true,
children: snapshot.data!.docs.map((document) {
return Padding(
padding: const EdgeInsets.symmetric(
horizontal: 16),
child: Card(
color: const Color.fromRGBO(
255, 255, 255, 1)
.withOpacity(0.6),
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(15),
),
child: Column(
children: <Widget>[
Text(data['name']),
Text(data['email']),
Text(data['bloodType']),
Text(data['dob']),
],
),
),
);
}).toList(),
);
}
}
)
]
)
}
}
Related
I need to show the data that I add at the top, but it does not happen, I thought that the data is arranged according to the date it was added to the Firebase Firestore,
I think the data is sorted by document ID
After I almost finished the application, I could not solve this problem, I am not very skilled in Firebase and I did not find the solution
class News extends StatefulWidget {
News({Key? key}) : super(key: key);
#override
State<News> createState() => _NewsState();
}
class _NewsState extends State<News> {
final Stream<QuerySnapshot> data =
FirebaseFirestore.instance.collection('news').snapshots();
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color.fromARGB(255, 102, 102, 102),
appBar: AppBar(
backgroundColor: Colors.blueAccent,
title: Center(
child: Text(
'أخبار الأنمي',
style: TextStyle(fontSize: 30),
),
),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: StreamBuilder<QuerySnapshot>(
stream: data,
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
return Text('Øدث خطأ');
}
if (snapshot.connectionState == ConnectionState.waiting) {
return Column(
children: [
Center(child: Text('جاري التØميل')),
CircularProgressIndicator()
],
);
}
final anime = snapshot.requireData;
return ListView.builder(
physics: BouncingScrollPhysics(),
padding:
EdgeInsets.only(top: 3, left: 3, right: 3, bottom: 80),
itemCount: anime.size,
itemBuilder: (context, index) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(color: Colors.blue, width: 3),
boxShadow: [
BoxShadow(
color: Colors.black,
blurRadius: 3.5,
spreadRadius: 1,
)
],
),
margin: EdgeInsets.all(5),
child: Row(
children: [
Expanded(
flex: 3,
child: Container(
alignment: Alignment.centerRight,
child: Text(
textDirection: TextDirection.rtl,
'${anime.docs[index]['title']}',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w700),
),
)),
Expanded(
flex: 1,
child: Card(
child: Image.network(
'${anime.docs[index]['image']}',
fit: BoxFit.fill,
height: 120,
),
),
)
],
),
),
],
);
});
})),
);
}
}
Yes, firestore will return base on alphabetically sorting based on document ID.
Use the .orderBy("FieldToOrderBy") to return it in your desired order.
Order and limit data - Firestore
so this is the create quiz interface where the teacher can insert the title of the quiz , the question and the option
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:mr_quiz/DB_helper.dart';
import 'package:random_string/random_string.dart';
import 'DB_helper.dart';
import 'question.dart';
import 'qcm.dart';
import 'choix.dart';
import 'folder.dart';
class Create_Quiz extends StatefulWidget {
#override
_Create_QuizState createState() => _Create_QuizState();
}
class _Create_QuizState extends State<Create_Quiz> {
bool choix = false;
late String question;
late String option;
late String titre;
String qst_id=randomAlphaNumeric(16);
String op_id=randomAlphaNumeric(16);
String qcm_id=randomAlphaNumeric(16);
TextEditingController titre_ctrl=TextEditingController();
TextEditingController qst_ctrl=TextEditingController();
TextEditingController choix_ctrl=TextEditingController();
add_qst(Question question){
DB_helper.instance.insertquestion(question);
print('question ajoutée');
}
add_qcm(Qcm qcm){
DB_helper.instance.insertqcm(qcm);
print('qcm ajouté');
}
add_choix(Choix choix){
DB_helper.instance.insertchoix(choix);
print('choix ajouté');
}
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
fontFamily: 'HindGuntur',
),
debugShowCheckedModeBanner: false,
title: 'Mr.Quiz',
routes: {
'/folder': (BuildContext context) => Folder()},
home: Builder(builder: (context) => Scaffold(
backgroundColor: Colors.white,
resizeToAvoidBottomInset: false,
appBar: AppBar(
backgroundColor: Colors.white,
title: Text('QCM', style: TextStyle(
color: Colors.black, fontWeight: FontWeight.bold),),
centerTitle: true,
elevation: 0.0,
leading: IconButton(icon: Icon(Icons.arrow_back),
onPressed: () {},
color: Colors.deepPurple,),
),
body: SingleChildScrollView(
child: Column(
children: <Widget>[
Center(child: Container(
height: 160.0,
width: 650.0,
margin: EdgeInsets.fromLTRB(30, 15, 30, 15),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30.0),
color: Colors.deepPurple.shade50,),
child: Column(
children: <Widget>[
SizedBox(height: 15.0,),
Text("Entrez le titre du QCM:",
style: TextStyle(fontWeight: FontWeight.bold,),
),
Container(
width: 300.0,
child: TextFormField(
controller: titre_ctrl,
decoration: InputDecoration(
filled: true,
fillColor: Colors.white,
contentPadding: EdgeInsets.fromLTRB(20, 10, 5,
10),
hintText: 'Titre',
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.deepPurple,),
borderRadius: BorderRadius.circular(30.0),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.deepPurple.shade200,),
borderRadius: BorderRadius.circular(30.0),
),
),
),
),
],
),
),
),
SizedBox(height: 20.0,),
Container(
width: 350.0,
child: TextFormField(
controller: qst_ctrl,
decoration: InputDecoration(
contentPadding: EdgeInsets.fromLTRB(10, 10, 10, 10),
hintText: 'Question ',
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.deepPurple.shade100,),
borderRadius: BorderRadius.circular(30.0),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.deepPurple.shade200,),
borderRadius: BorderRadius.circular(30.0),
),
),
),
),
SizedBox(height: 20.0,),
Row(
children: [
Expanded(
flex: 6,
child: TextFormField(
controller: choix_ctrl,
decoration: InputDecoration(
hintText: "option ",
contentPadding: EdgeInsets.fromLTRB(20, 10, 10, 10),
),
),
),
Flexible(
child: SizedBox(
width: 5,
child: Checkbox(value: choix,
onChanged: (val) {
setState(() {
choix= val!;
});
},
activeColor: Colors.deepPurple,
checkColor: Colors.white,
),
),
)
],
),
Row(
children: <Widget>[
SizedBox(width: 120.0),
Icon(Icons.add_circle_outline, color: Colors.deepPurple,
size: 22.0,),
TextButton(
child: Text(
'ajouter un choix', textAlign: TextAlign.center,
style: TextStyle(
color: Colors.deepPurple, fontSize: 16.0),),
onPressed: () {setState(() {
option=choix_ctrl.text;
});
Choix choice =new Choix(op_id,option,choix);
add_choix(choice);
choix_ctrl.clear();},
),
],
),
SizedBox(height: 30.0,),
Column(
children: <Widget>[
ElevatedButton(style: ElevatedButton.styleFrom(
primary: Colors.deepPurple.shade200,
fixedSize: Size(300.0, 50.0),
elevation: 0.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30.0)),
),
child:
Text('Ajouter Question',
style: TextStyle(fontSize: 16.0),),
onPressed: () {setState(() {
question=qst_ctrl.text;
});
Question qst =new Question(qst_id,question);
add_qst(qst);
qst_ctrl.clear();},),
SizedBox(height: 20.0,),
ElevatedButton(style: ElevatedButton.styleFrom(
primary: Colors.indigo.shade400,
fixedSize: Size(250.0, 50.0),
elevation: 0.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30.0)),
),
child:
Text(
'valider mon QCM', style: TextStyle(fontSize: 16.0),),
onPressed: () {setState(() {
titre=titre_ctrl.text;
});
Qcm qcm =new Qcm(qcm_id,titre);
add_qcm(qcm);
Navigator.pushNamed(context, '/folder');
},),
],
),
SizedBox(height: 10.0,),
],),
),
),
)
);
}`
this is the folder interface where the quiz title is displayed
import 'package:flutter/material.dart';
import 'DB_helper.dart';
import'package:mr_quiz/createquiz.dart';
import 'qcm.dart';
import 'package:mr_quiz/question.dart';
import 'package:mr_quiz/choix.dart';
class Folder extends StatefulWidget {
const Folder({Key? key}) : super(key: key);
#override
_FolderState createState() => _FolderState();
}
class _FolderState extends State<Folder> {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
fontFamily: 'HindGuntur',
),
debugShowCheckedModeBanner: false,
title: 'Mes QCM',
home: Scaffold(
resizeToAvoidBottomInset: false,
backgroundColor: Colors.white,
appBar: AppBar(backgroundColor: Colors.deepPurple.shade200,
elevation: 0.0,
centerTitle: true,
title: Text(
"Mes QCM",
style:
TextStyle(
color: Colors.white,
fontWeight: FontWeight.w500,
),
),
),
body:FutureBuilder<List<Qcm>>(
future : DB_helper.instance.qcms(),
builder: (BuildContext context, AsyncSnapshot<List<Qcm>> snapshot) {
if (snapshot.hasData) {
List<Qcm>? qcms = snapshot.data;
return ListView.builder(
itemCount: qcms?.length,
itemBuilder: (context, index){
final qcm = qcms![index];
return Dismissible(key: Key(qcm.qcm_id),
onDismissed: (direction){
setState(() {
DB_helper.instance.deleteprofil(qcm.qcm_id);
});
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("${qcm.titre} supprimé")));
},
background: Container(color: Colors.red),
child: ProfWidget(qcm: qcm, ));
},
);
} else {
return Center(child: CircularProgressIndicator());
}
}
),
)
);
}
}
class ProfWidget extends StatelessWidget {
const ProfWidget({Key? key, required this.qcm}) : super(key: key);
final Qcm qcm;
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: (){
},
child: Card(
margin: EdgeInsets.all(8),
elevation: 8,
child: Row(
children: [
Padding(
padding: EdgeInsets.all(8),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: const EdgeInsets.only(bottom: 8),
child: Text(qcm.titre,
style:
TextStyle(fontWeight: FontWeight.bold, fontSize: 20)),
),
],
),
)
],
),
),
);
}
}
only the loading indicator is showing could anyone please help me solve this problem , and also can anyone please tell me how to display the data in the playquiz interface , we have a table for each model and they're related to each other with foreign keys but i don't know how to display data from them like i want to display the questions that belong to the same quiz and the options for each question
import 'package:flutter/material.dart';
import 'package:stone_recipe_app/homepage.dart';
import 'package:stone_recipe_app/models/recipe.dart';
import 'package:share_plus/share_plus.dart';
class DetailedScreen extends StatelessWidget {
DetailedScreen({Key? key, required this.recipe, required this.index}) : super(key: key);
List<Recipe>? recipe;
int index;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: Row(
children: [
IconButton(
icon: const Icon(Icons.arrow_back_ios),
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (context) => HomePage()));
},
),
Text(
'Back',
style: TextStyle(color: Color(0xff007AFF)),
)
],
),
iconTheme: const IconThemeData(color: Color(0xff007AFF)),
title: Center(
child: Text(
recipe![index].recipe_name,
style: TextStyle(color: Colors.black),
),
),
backgroundColor: Colors.white,
elevation: 0,
),
body: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Column(
children: [
Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(200),
),
child: Container(
width: 400,
height: 200,
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(9.0)),
image: DecorationImage(
image: AssetImage("images/cook.jpg"),
fit: BoxFit.cover,
),
boxShadow: [
BoxShadow(
blurRadius: 5,
color: Colors.black,
)
],
),
),
),
Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
const Icon(
Icons.file_download_sharp,
color: Colors.blue,
size: 40,
),
const Icon(
Icons.document_scanner,
size: 40,
),
IconButton(
onPressed: () {
Share.share(recipe![index].recipe_prep);
},
icon: const Icon(
Icons.share,
color: Colors.blue,
size: 40,
)),
const Icon(
Icons.favorite,
color: Colors.red,
size: 40,
),
]),
SizedBox(
height: 500,
child: Card(
elevation: 4,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Center(
child: Text(
'Ingredients',
style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold),
),
),
Column(
children: [
Text(recipe![index].recipe_ingrdients),
],
),
Center(
child: Text(
'Method',
style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold),
),
),
Text(
recipe![index].recipe_prep,
style: TextStyle(
fontSize: 20,
),
)
],
),
),
)
],
),
),
);
// Scaffold(
// appBar: AppBar(
// title: Text(recipe![index].recipe_name),
// ),
// body: Center(
// child: SingleChildScrollView(
// child: Column(
// mainAxisSize: MainAxisSize.min,
// children: [
// SelectableText(recipe![index].recipe_cat),
// Text(recipe![index].recipe_prep),
// Text(recipe![index].recipe_id.toString()),
// Text(recipe![index].recipe_ingrdients),
// Text(recipe![index].image_name),
// OutlinedButton(
// onPressed: () {
// Share.share(recipe![index].recipe_prep);
// },
// child: Text('Share'))
// ],
// ),
// ),
// ),
// );
}
}
import 'package:flutter/material.dart';
import 'package:stone_recipe_app/detailedScreen.dart';
import 'package:stone_recipe_app/models/recipe.dart';
import 'package:stone_recipe_app/services/db_services.dart';
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
#override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
final dbservice = DataBaseService();
#override
void dispose() {
dbservice.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Recipe App')),
body: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: FutureBuilder<List<Recipe>>(
future: dbservice.getRecipe(),
builder: (context, snapshot) {
if (!snapshot.hasData) return Center(child: CircularProgressIndicator());
return ListView.builder(
shrinkWrap: true,
itemCount: snapshot.data?.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DetailedScreen(
recipe: snapshot.data,
index: index,
)));
},
title: Text(snapshot.data![index].recipe_name, style: TextStyle(color: Colors.black)),
// trailing: Text(
// snapshot.data![index].recipe_cat,
// style: TextStyle(color: Colors.black),
// overflow: TextOverflow.fade,
// ),
);
},
);
},
)),
);
}
}
enter image description herei am trying to show data from sqlite db in flutter when user click on country category like india china after user click user navigate to other page which are recipe name related to chine or related to india i am trying to show data from sqlite db in flutter when user click on country category like india china after user click user navigate to other page which are recipe name related to chine or related to india enter image description here
add group_list_view: ^1.1.1 package in your pubspec.yaml file.
try below the example then implement it in your project
import 'package:flutter/material.dart';
import 'package:group_list_view/group_list_view.dart';
import 'package:group_listview_example/app_colors.dart';
void main() => runApp(MyApp());
Map<String, List> _elements = {
'Team A': ['Klay Lewis', 'Ehsan Woodard', 'River Bains'],
'Team B': ['Toyah Downs', 'Tyla Kane'],
'Team C': ['Marcus Romero', 'Farrah Parkes', 'Fay Lawson', 'Asif Mckay'],
'Team D': [
'Casey Zuniga',
'Ayisha Burn',
'Josie Hayden',
'Kenan Walls',
'Mario Powers'
],
'Team Q': ['Toyah Downs', 'Tyla Kane', 'Toyah Downs'],
};
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Group List View Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(
title: Text('Group List View Demo'),
),
body: GroupListView(
sectionsCount: _elements.keys.toList().length,
countOfItemInSection: (int section) {
return _elements.values.toList()[section].length;
},
itemBuilder: _itemBuilder,
groupHeaderBuilder: (BuildContext context, int section) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 8),
child: Text(
_elements.keys.toList()[section],
style: TextStyle(fontSize: 18, fontWeight: FontWeight.w600),
),
);
},
separatorBuilder: (context, index) => SizedBox(height: 10),
sectionSeparatorBuilder: (context, section) => SizedBox(height: 10),
),
),
);
}
Widget _itemBuilder(BuildContext context, IndexPath index) {
String user = _elements.values.toList()[index.section][index.index];
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: Card(
elevation: 8,
child: ListTile(
contentPadding:
const EdgeInsets.symmetric(horizontal: 18, vertical: 10.0),
leading: CircleAvatar(
child: Text(
_getInitials(user),
style: TextStyle(color: Colors.white, fontSize: 18),
),
backgroundColor: _getAvatarColor(user),
),
title: Text(
_elements.values.toList()[index.section][index.index],
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w400),
),
trailing: Icon(Icons.arrow_forward_ios),
),
),
);
}
String _getInitials(String user) {
var buffer = StringBuffer();
var split = user.split(" ");
for (var s in split) buffer.write(s[0]);
return buffer.toString().substring(0, split.length);
}
Color _getAvatarColor(String user) {
return AppColors
.avatarColors[user.hashCode % AppColors.avatarColors.length];
}
}
I am putting up 3 .dart files which are required for the app.
StaffEvent.dart
import 'package:flutter/material.dart';
import 'package:flutter_new_app/addevent_screen.dart';
import 'package:flutter_new_app/services/crud.dart';
class StaffEvent extends StatefulWidget {
#override
_StaffEventState createState() => _StaffEventState();
}
class _StaffEventState extends State<StaffEvent> {
CrudMethods crudMethods = new CrudMethods();
QuerySnapshot eventSnapshot;
Stream eventStream;
// ignore: non_constant_identifier_names
Widget EventList() {
return Container(
child: eventStream != null
? Column(
children: [
StreamBuilder(
stream: eventStream,
builder: (context, snapshot) {
return ListView.builder(
padding: EdgeInsets.symmetric(horizontal: 16),
itemCount: eventSnapshot.docs.length,
shrinkWrap: true,
itemBuilder: (context, index) {
return EventTile(
title: eventSnapshot.docs[index].data()['title'],
desc: eventSnapshot.docs[index].data()['desc'],
date: eventSnapshot.docs[index].data()['date'],
);
},
);
},
),
],
)
: Container(
alignment: Alignment.center,
child: CircularProgressIndicator(),
),
);
}
#override
void initState() {
setState(() {
Stream result;
eventStream = result;
});
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color(0xFFffffff),
appBar: AppBar(
actions: [
FloatingActionButton(
backgroundColor: Colors.green,
child: Icon(Icons.add),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => AddEvent()),
);
},
)
],
backgroundColor: Color(0xFFebd8b7),
title: Text(
'Events',
style: TextStyle(color: Colors.black),
),
),
);
}
}
// ignore: must_be_immutable
class EventTile extends StatelessWidget {
String title, desc, date;
EventTile({#required this.title, #required this.desc, #required this.date});
#override
Widget build(BuildContext context) {
return Column(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(6),
child: SizedBox(
width: 500,
height: 80,
child: Container(
color: Color(0xFFeaffd0),
child: Column(
children: [
Text(
title,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 25, fontWeight: FontWeight.w500),
),
Text(
desc,
style: TextStyle(fontSize: 17, fontWeight: FontWeight.w400),
),
Text(
date,
style: TextStyle(fontSize: 17, fontWeight: FontWeight.w400),
)
],
),
),
),
),
],
);
}
}
Crud.dart
import 'package:cloud_firestore/cloud_firestore.dart';
class CrudMethods {
Future<void> addData(eventData) async {
FirebaseFirestore.instance
.collection("events")
.add(eventData)
.catchError((e) {
print(e);
});
}
getData() async {
return await FirebaseFirestore.instance.collection("events").get();
}
}
Addevent.dart
import 'package:flutter_new_app/services/crud.dart';
class AddEvent extends StatefulWidget {
#override
_AddEventState createState() => _AddEventState();
}
class _AddEventState extends State<AddEvent> {
String title, desc, date;
CrudMethods crudMethods = new CrudMethods();
uploadEvent() async {
Map<String, String> eventMap = {"title": title, "desc": desc, "date": date};
crudMethods.addData(eventMap).then((result) {
Navigator.pop(context);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color(0xFFffffff),
appBar: AppBar(
backgroundColor: Color(0xFFf38181),
title: Text(
'Add Event',
style: TextStyle(color: Colors.black),
),
actions: <Widget>[
GestureDetector(
onTap: () {
uploadEvent();
},
child: Container(
padding: EdgeInsets.symmetric(horizontal: 16),
child: Icon(Icons.file_upload)),
)
],
),
body: Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
decoration: InputDecoration(hintText: "Event Name"),
onChanged: (val) {
title = val;
},
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
decoration: InputDecoration(hintText: "Description"),
onChanged: (val) {
desc = val;
},
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
decoration: InputDecoration(hintText: "Date"),
onChanged: (val) {
date = val;
},
),
)
],
));
}
}
So here basically, the user has to enter some details for an event and when clicking the upload button it should be visible as a list in the Staffevent page . That is the problem. Nothung is showing in the Staffevent page. It is blank.
The data is being stored in the firebase database but when i am using snapshot and calling it back it is not showing in my flutter application.
Your stream is empty:
Stream result;
eventStream = result;
Firebase Firestore get() method returns a Future<DocumentSnapshot>:
Future<DocumentSnapshot> getData() async {
return await FirebaseFirestore.instance.collection("events").get();
}
If you need a stream you use snapshots() method which returns a Stream:
Stream collectionStream = FirebaseFirestore.instance.collection("events").snapshots();
Please refer to official documentation to get familiar with Firebase API.
I am trying to add some city list to a dialog with checkbox so that i need to implement multiple click on items. what I am trying to do is given below.
onPressed from button calls Rest Service and on success result I just show a dialog
void showCityDialog(BuildContext context) {
SimpleDialog dialog = new SimpleDialog(
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
new Text(
"CITIES",
style: TextStyle(fontSize: 18.0, color: Colors.black),
textAlign: TextAlign.center,
),
new RaisedButton(
onPressed: () {print("clicked");},
color: Color(0xFFfab82b),
child: new Text(
"Done",
style: TextStyle(color: Colors.white),
),)],),
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new Container(
constraints: BoxConstraints(maxHeight: 500.0),
child: ListView.builder(
scrollDirection: Axis.vertical,
itemCount: cityData.length,
itemBuilder: (context, position) {
return new CheckboxListTile(
value: checkboxValueCity,
onChanged: (bool value) {
setState(() {
checkboxValueCity = value;
});
},
activeColor: Color(0xFFfab82b),
dense: true,
title: Text(
cityData[position].city_name,
style: TextStyle(fontSize: 16.0, color: Colors.black),
),);},),),],)],);
showDialog(
context: context,
builder: (BuildContext context) {
return dialog;
});
}
checkboxValueCity is a boolean variable in class , on click of chekboxListItem i need to update checkbox value as checked and uncheced. At the same time need to add/remove that item to a list which is also inside that class.
But in my code checkbox is not refershing on every click but when i close that box and open it again checkbox is checked. then how can i get multiple click from tile and how can i return list from dialog?
Your dialog needs to be a StatefulWidget (Flutter Github issue). The member variable that tracks selection state needs to be in the dialog class. You can use a callback to update a member variable in your parent class with the List of selected cities. There also seem to be some issues using a ListView.builder inside of a SimpleDialog or AlertDialog (search the Flutter Github for issues) so I used a plain Dialog.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Checkbox Dialog Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Checkbox Dialog Demo'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool checkboxValueCity = false;
List<String> allCities = ['Alpha', 'Beta', 'Gamma'];
List<String> selectedCities = [];
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
showDialog(
context: context,
builder: (context) {
return _MyDialog(
cities: allCities,
selectedCities: selectedCities,
onSelectedCitiesListChanged: (cities) {
selectedCities = cities;
print(selectedCities);
});
});
}),
);
}
}
class _MyDialog extends StatefulWidget {
_MyDialog({
this.cities,
this.selectedCities,
this.onSelectedCitiesListChanged,
});
final List<String> cities;
final List<String> selectedCities;
final ValueChanged<List<String>> onSelectedCitiesListChanged;
#override
_MyDialogState createState() => _MyDialogState();
}
class _MyDialogState extends State<_MyDialog> {
List<String> _tempSelectedCities = [];
#override
void initState() {
_tempSelectedCities = widget.selectedCities;
super.initState();
}
#override
Widget build(BuildContext context) {
return Dialog(
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
'CITIES',
style: TextStyle(fontSize: 18.0, color: Colors.black),
textAlign: TextAlign.center,
),
RaisedButton(
onPressed: () {
Navigator.pop(context);
},
color: Color(0xFFfab82b),
child: Text(
'Done',
style: TextStyle(color: Colors.white),
),
),
],
),
Expanded(
child: ListView.builder(
itemCount: widget.cities.length,
itemBuilder: (BuildContext context, int index) {
final cityName = widget.cities[index];
return Container(
child: CheckboxListTile(
title: Text(cityName),
value: _tempSelectedCities.contains(cityName),
onChanged: (bool value) {
if (value) {
if (!_tempSelectedCities.contains(cityName)) {
setState(() {
_tempSelectedCities.add(cityName);
});
}
} else {
if (_tempSelectedCities.contains(cityName)) {
setState(() {
_tempSelectedCities.removeWhere(
(String city) => city == cityName);
});
}
}
widget
.onSelectedCitiesListChanged(_tempSelectedCities);
}),
);
}),
),
],
),
);
}
}
Use StatefulBuilder to update Widgets only inside Dialog. StatefulBuilder is best for update sebsection of the widget tree where
state is needed.
simple code snippet
void _showDialog() {
showDialog(
context: context,
builder: (context) {
return StatefulBuilder( // StatefulBuilder
builder: (context, setState) {
return AlertDialog(
actions: <Widget>[
Container(
width: 400,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(
"Student Attendence",
style: TextStyle(fontSize: 20),
),
SizedBox(
height: 5,
),
Container(
height: 2,
color: Colors.black,
),
SizedBox(
height: 15,
),
CheckboxListTile(
value: user1,
title: Text("user1"),
onChanged: (value){
setState(() {
user1=value;
});
},
),
Divider(
height: 10,
),
CheckboxListTile(
value: user2,
title: Text("user2"),
onChanged: (value){
setState(() {
user2=value;
});
},
),
Divider(
height: 10,
),
CheckboxListTile(
value: user3,
title: Text("user3"),
onChanged: (value){
setState(() {
user3=value;
});
},
),
Divider(
height: 10,
),
CheckboxListTile(
value: user4,
title: Text("user4"),
onChanged: (value){
setState(() {
user4=value;
});
},
),
Divider(
height: 10,
),
SizedBox(
height: 5,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Material(
elevation: 5.0,
color: Colors.blue[900],
child: MaterialButton(
padding: EdgeInsets.fromLTRB(
10.0, 5.0, 10.0, 5.0),
onPressed: () {},
child: Text("Save",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 15,
)),
),
),
Material(
elevation: 5.0,
color: Colors.blue[900],
child: MaterialButton(
padding: EdgeInsets.fromLTRB(
10.0, 5.0, 10.0, 5.0),
onPressed: () {
setState(() {
Navigator.of(context).pop();
});
},
child: Text("Cancel",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 15,
)),
),
),
Material(
elevation: 5.0,
color: Colors.blue[900],
child: MaterialButton(
padding: EdgeInsets.fromLTRB(
10.0, 5.0, 10.0, 5.0),
onPressed: () {},
child: Text("Select All",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 15,
)),
),
),
],
)
],
))
],
);
},
);
},
);
}
example
Although Albert's answer works, you need not go thru all that. Simply wrap the content: with a StatefulBuilder, voila!
https://api.flutter.dev/flutter/widgets/StatefulBuilder-class.html.
Note: It is important where you declare the variable(s) you want to change.
I modified your code a bit, I want when users check the list, the list won't be updated to the main view, but they will when users click the "Update" button.
But some how, it doesn't work. Can you please check ?
Thank you very much
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Checkbox Dialog Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Checkbox Dialog Demo'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool checkboxValueCity = false;
List<String> allCities = ['Alpha', 'Beta', 'Gamma'];
List<String> selectedCities = [];
List<String> selectedCitiesTemp = [];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("App Bar"),
),
body: Center(
child: Column(
children: <Widget>[
_list(),
RaisedButton(
child: Text("Update From TMP List"),
onPressed: () {
setState(() {
selectedCities = selectedCitiesTemp;
});
},
)
],
),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
showDialog(
context: context,
builder: (BuildContext context) {
return _MyDialog(
cities: allCities,
selectedCities: selectedCities,
onSelectedCitiesListChanged: (cities) {
setState(() {
selectedCitiesTemp = cities;
});
},
);
});
}),
);
}
Widget _list() {
List<Widget> list = [];
for(String item in selectedCities) {
list.add(ListTile(
title: Text(item),
));
}
return Column(
children: list
);
}
}
class _MyDialog extends StatefulWidget {
_MyDialog({
this.cities,
this.selectedCities,
this.onSelectedCitiesListChanged,
});
final List<String> cities;
final List<String> selectedCities;
final ValueChanged<List<String>> onSelectedCitiesListChanged;
#override
_MyDialogState createState() => _MyDialogState();
}
class _MyDialogState extends State<_MyDialog> {
List<String> _tempSelectedCities = [];
#override
void initState() {
_tempSelectedCities = widget.selectedCities;
super.initState();
}
#override
Widget build(BuildContext context) {
return Dialog(
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
'CITIES',
style: TextStyle(fontSize: 18.0, color: Colors.black),
textAlign: TextAlign.center,
),
],
),
Expanded(
child: ListView.builder(
itemCount: widget.cities.length,
itemBuilder: (BuildContext context, int index) {
final cityName = widget.cities[index];
return Container(
child: CheckboxListTile(
title: Text(cityName),
value: _tempSelectedCities.contains(cityName),
onChanged: (bool value) {
if (value) {
if (!_tempSelectedCities.contains(cityName)) {
setState(() {
_tempSelectedCities.add(cityName);
});
}
} else {
if (_tempSelectedCities.contains(cityName)) {
setState(() {
_tempSelectedCities.removeWhere(
(String city) => city == cityName);
});
}
}
widget.onSelectedCitiesListChanged(_tempSelectedCities);
}),
);
}),
),
],
),
);
}
}