This is a part of a project regarding feedback forms.
I already manage to create the validation form properly thanks to the answers here in StackOverflow developers.
But the problem is creating this regular expression which seems to not work on the validation form. I found in flutter docs the Iterable but I do not know how can I implement it on the dart page.
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
class SimpleDialog extends StatelessWidget {
// ignore: prefer_typing_uninitialized_variables
final title;
const SimpleDialog(this.title, {super.key});
#override
Widget build(BuildContext context) {
return AlertDialog(
title: const Text('Alert'),
content: Text(title),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: const Text('OK'))
],
);
}
}
class FeedbackPage extends StatefulWidget {
const FeedbackPage({super.key});
#override
State<FeedbackPage> createState() => _FeedbackPageState();
}
class _FeedbackPageState extends State<FeedbackPage> {
final nameOfuser = TextEditingController();
final emailOfuser = TextEditingController();
final messageOfuser = TextEditingController();
final _formKey = GlobalKey<FormState>();
List<bool> isTypeSelected = [false, false, false, true, true];
#override
Widget build(BuildContext context) {
return Scaffold(
// AppBar para sa taas ng design
appBar: AppBar(
centerTitle: true,
title: const Text(
"PicLeaf",
style: TextStyle(
color: Color.fromRGBO(102, 204, 102, 1.0),
fontWeight: FontWeight.bold),
),
backgroundColor: Colors.white,
shadowColor: const Color.fromARGB(255, 95, 94, 94),
),
//body of the application
backgroundColor: const Color(0xffeeeeee),
body: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
const SizedBox(
height: 20,
),
const Text(
"Feedback",
style: TextStyle(
fontSize: 30.0,
fontFamily: 'RobotoBold',
fontWeight: FontWeight.bold,
color: Color.fromRGBO(102, 204, 102, 1.0)),
),
const Text(
"Give us your feedback!",
style: TextStyle(
fontSize: 18.0,
fontFamily: 'RobotoMedium',
),
),
const SizedBox(
height: 20,
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 32.0),
child: Form(
key: _formKey,
child: Column(
children: <Widget>[
const SizedBox(height: 16.0),
TextFormField(
controller: nameOfuser,
decoration: const InputDecoration(
filled: true,
fillColor: Colors.white,
hintText: "Name",
border: OutlineInputBorder(),
),
validator: (nameOfuser) {
if (nameOfuser == null || nameOfuser.isEmpty) {
return 'Please enter your Name';
}
return null;
},
),
const SizedBox(height: 8.0),
TextFormField(
controller: emailOfuser,
decoration: const InputDecoration(
filled: true,
fillColor: Colors.white,
hintText: "Email",
border: OutlineInputBorder(),
),
validator: (emailOfuser) {
if (emailOfuser == null || emailOfuser.isEmpty) {
String emailOfuser1 = emailOfuser.toString();
String pattern = r'\w+#\w+\.\w+';
if (RegExp(pattern).hasMatch(emailOfuser1)) {
return 'Please enter your Email Properly';
} else {
return 'Please enter your Email';
}
}
return null;
},
),
const SizedBox(height: 8.0),
TextFormField(
controller: messageOfuser,
maxLines: 6,
decoration: const InputDecoration(
filled: true,
fillColor: Colors.white,
hintText: "Message",
border: OutlineInputBorder(),
),
validator: (messageOfuser) {
if (messageOfuser == null || messageOfuser.isEmpty) {
return 'Please enter your Message';
}
return null;
},
),
const SizedBox(height: 8.0),
MaterialButton(
height: 50.0,
minWidth: double.infinity,
color: const Color.fromRGBO(102, 204, 102, 1.0),
onPressed: () {
if (_formKey.currentState!.validate()) {
showDialog(
context: context,
builder: (BuildContext context) {
return const SimpleDialog(
'Feedback Submitted');
});
Map<String, dynamic> data = {
"Name": nameOfuser.text,
"Email": emailOfuser.text,
"Message": messageOfuser.text,
"Time": FieldValue.serverTimestamp(),
};
setState(() {
nameOfuser.clear();
emailOfuser.clear();
messageOfuser.clear();
});
FirebaseFirestore.instance
.collection("FeedbackMessages")
.add(data);
}
},
child: const Text(
"SUBMIT",
style: TextStyle(
fontFamily: 'RobotoBold',
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
),
const SizedBox(
height: 10,
),
Container(
padding: const EdgeInsets.fromLTRB(20, 20, 20, 10),
child: const Text(
'Contact Us!',
style: TextStyle(
fontSize: 30,
fontFamily: 'RobotoBold',
color: Color.fromRGBO(102, 204, 102, 1.0)),
textAlign: TextAlign.center,
),
),
Column(
children: <Widget>[
Container(
padding: const EdgeInsets.fromLTRB(20, 0, 20, 0),
margin: const EdgeInsets.symmetric(horizontal: 0),
child: TextButton.icon(
// <-- TextButton
onPressed: () {},
icon: const Icon(
Icons.facebook,
color: Colors.black,
size: 35.0,
),
label: const Text(
'facebook.com/picleaf',
style: TextStyle(fontFamily: 'RobotoMedium'),
),
style: TextButton.styleFrom(
foregroundColor: Colors.black,
),
),
),
Container(
padding: const EdgeInsets.fromLTRB(20, 0, 20, 10),
margin: const EdgeInsets.symmetric(horizontal: 0),
child: TextButton.icon(
// <-- TextButton
onPressed: () {},
icon: const Icon(
Icons.email,
color: Colors.black,
size: 35.0,
),
label: const Text(
'picleaf#gmail.com',
style: TextStyle(fontFamily: 'RobotoMedium'),
),
style: TextButton.styleFrom(
foregroundColor: Colors.black,
),
)),
],
)
],
),
),
),
],
),
));
}
}
You can use this validator:
validator: (emailOfuser) {
if (emailOfuser == null || emailOfuser.isEmpty) {
return 'Please enter your Email';
} else if (emailOfuser.isNotEmpty) {
String emailOfuser1 = emailOfuser.toString();
String pattern = r'\w+#\w+\.\w+';
if (RegExp(pattern).hasMatch(emailOfuser1) == false) {
return 'Please enter your Email Properly';
}
}
return null;
},
try to implement like this:
import 'package:flutter/material.dart';
class EmailValidationForm extends StatefulWidget {
const EmailValidationForm({Key? key}) : super(key: key);
#override
State<EmailValidationForm> createState() => _EmailValidationFormState();
}
class _EmailValidationFormState extends State<EmailValidationForm> {
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Email Validation'),
),
body: Form(
key: formKey,
child: Column(
children: [
TextFormField(
autofocus: false,
maxLength: 300,
keyboardType: TextInputType.emailAddress,
autocorrect: false,
validator: (email) {
if (email!.isEmpty) {
return 'required field';
} else if (email.trim().contains(' ')) {
return 'contain space';
} else if (!emailValid(email)) {
return 'invalid email';
}
return null;
},
onSaved: (email) {
return debugPrint(email);
},
),
ElevatedButton(
onPressed: () {
if (formKey.currentState!.validate()) {
formKey.currentState!.save();
}
},
child: const Text('Validate')),
],
),
),
);
}
}
bool emailValid(String email) {
final RegExp regex = RegExp(
r"^(([^<>()[\]\\.,;:\s#\']+(\.[^<>()[\]\\.,;:\s#\']+)*)|(\'.+\'))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$");
return regex.hasMatch(email.trim());
}
Related
I am trying to create form.
I managed to create every widget in it, but every time I try to open TextFormField I get redirected back to my MainMenuScreen without any error.
I am using BLoC and routes. I think that issue might be related with using named routes.
Issue was not spotted before changing to named routes
MainMenuScreen fragment:
CategoryCard(
categoryName: 'Main dishes',
assetPath: 'assets/images/main_dish.png',
onPressed: () => Navigator.pushReplacement(context,
MaterialPageRoute(builder: (BuildContext context) {
return BlocProvider.value(
value: BlocProvider.of<RecipesBloc>(context)
..add(LoadRecipesEvent())
..category = 'main_dish',
child: RecipesScreen(),
);
})),
),
From MainMenuScreen I redirect to RecipesScreen
Fragment of RecipesScreen with redirect to RecipeCreateForm:
floatingActionButton: FloatingActionButton(
onPressed: () => Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (BuildContext context) {
return RecipeCreateForm();
}),
),
and then I redirect to RecipeCreateForm where I'm using TextFormFields.
Whenever I try to use TextFormField I get redirected back to MainMenuScreen.
class RecipeCreateForm extends StatefulWidget {
#override
_RecipeCreateFormState createState() => _RecipeCreateFormState();
}
class _RecipeCreateFormState extends State<RecipeCreateForm> {
final _recipeNameController = TextEditingController();
final _imageUrl = TextEditingController();
String? _difficultyValue;
late int _ingredientsQuantity;
late int _preparationStepsQuantity;
late List<Ingredient> _ingredientsValues;
late List<PreparationStep> _preparationStepsValues;
late double _preparationTime;
String? _portions;
#override
void initState() {
_ingredientsQuantity = 1;
_preparationStepsQuantity = 1;
_ingredientsValues = [];
_preparationStepsValues = [];
_preparationTime = 0;
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: true,
appBar: AppBar(
leading: IconButton(
onPressed: () {
Navigator.of(context).pop();
},
icon: Icon(
Icons.arrow_back,
color: Colors.white,
),
),
),
body: Scrollbar(
thickness: 10,
hoverThickness: 2,
child: SingleChildScrollView(
child: Container(
color: Colors.lightGreen.shade100,
child: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: 15),
),
Text(
'Recipe name',
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20),
),
TextFormField(
style: TextStyle(
color: Colors.black,
fontSize: 18,
fontStyle: FontStyle.italic),
controller: _recipeNameController,
),
Padding(
padding: EdgeInsets.only(top: 15),
),
Text(
'Image',
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20),
),
TextFormField(
style: TextStyle(
color: Colors.black,
fontSize: 18,
fontStyle: FontStyle.italic),
controller: _imageUrl,
),
Padding(
padding: EdgeInsets.only(top: 15),
),
Text(
'Difficulty',
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20),
),
DropdownButton(
hint: _difficultyValue == null
? Text(
'Select difficulty',
style: TextStyle(
color: Colors.black,
fontSize: 18,
fontStyle: FontStyle.italic),
)
: Text(
_difficultyValue!,
style: TextStyle(
color: Colors.black,
fontSize: 18,
fontStyle: FontStyle.italic),
),
isExpanded: true,
iconSize: 30.0,
style: TextStyle(
color: Colors.black,
fontSize: 18,
fontStyle: FontStyle.italic),
items: ['Easy', 'Medium', 'Hard'].map(
(val) {
return DropdownMenuItem<String>(
value: val,
child: Text(val),
);
},
).toList(),
onChanged: (val) {
setState(
() {
_difficultyValue = val as String;
},
);
},
),
Padding(
padding: EdgeInsets.only(top: 15),
),
Text(
'Preparation time',
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20),
),
Slider(
value: _preparationTime,
onChanged: (newPreparationTime) {
setState(() => _preparationTime = newPreparationTime);
},
label: _preparationTime.toStringAsFixed(0),
min: 0,
max: 360,
divisions: 24,
),
Padding(
padding: EdgeInsets.only(top: 15),
),
Text(
'Ingredients',
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20),
),
SizedBox(
height: 175,
child: Scrollbar(
child: ListView.builder(
itemCount: _ingredientsQuantity,
itemBuilder: (context, index) {
return _ingredientRow(index);
}),
),
),
Row(
children: [
IconButton(
icon: Icon(Icons.add),
onPressed: () async {
setState(() {
_ingredientsQuantity++;
});
}),
IconButton(
icon: Icon(Icons.delete),
onPressed: () async {
setState(() {
_ingredientsQuantity = 1;
_ingredientsValues.clear();
});
})
],
),
Padding(
padding: EdgeInsets.only(top: 15),
),
Text(
'Preparation steps',
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20),
),
Scrollbar(
child: SizedBox(
height: 100,
child: ListView.builder(
shrinkWrap: true,
itemCount: _preparationStepsQuantity,
itemBuilder: (context, index) {
return _preparationStepRow(index);
}),
),
),
Row(
children: [
IconButton(
icon: Icon(Icons.add),
onPressed: () async {
setState(() {
_preparationStepsQuantity++;
});
}),
IconButton(
icon: Icon(Icons.delete),
onPressed: () async {
setState(() {
_preparationStepsQuantity = 1;
_preparationStepsValues.clear();
});
}),
],
),
Padding(
padding: EdgeInsets.only(top: 15),
),
Text(
'Portions',
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20),
),
DropdownButton(
hint: _portions == null
? Text(
'Select number of portions',
style: TextStyle(
color: Colors.black,
fontSize: 18,
fontStyle: FontStyle.italic),
)
: Text(
_portions!,
style: TextStyle(
color: Colors.black,
fontSize: 18,
fontStyle: FontStyle.italic),
),
isExpanded: true,
iconSize: 30.0,
style: TextStyle(
color: Colors.black,
fontSize: 18,
fontStyle: FontStyle.italic),
items: ['1', '2', '3', '4', '5', '6', '7'].map(
(val) {
return DropdownMenuItem<String>(
value: val,
child: Text(val),
);
},
).toList(),
onChanged: (val) {
setState(
() {
_portions = val as String;
},
);
},
),
ElevatedButton(
onPressed: () {
BlocProvider.of<RecipesBloc>(context).add(
AddRecipeEvent(
Recipe(
name: _recipeNameController.text,
image:
'https://www.thespruceeats.com/thmb/dA8o8EZpjJyeocYZNpzfknoKh2s=/4351x3263/smart/filters:no_upscale()/baked-stuffed-potatoes-482217-hero-01-850f2d87fe80403f923e140dbf5f1bf3.jpg',
ingredients: _ingredientsValues,
difficulty: _difficultyValue,
preparationTime: _preparationTime,
preparationSteps: _preparationStepsValues,
type: BlocProvider.of<RecipesBloc>(context)
.category
.toString(),
portions: _portions,
),
),
);
Navigator.of(context).pop();
},
child: Text('Submit'),
),
],
),
),
),
),
);
}
_ingredientRow(int key) {
return IntrinsicHeight(
child: Row(
children: [
Padding(padding: EdgeInsets.only(left: 10)),
SizedBox(
width: 225,
child: TextFormField(
maxLength: 35,
onChanged: (val) {
setState(() {
_onIngredientUpdate(key,name: val);
});
},
),
),
VerticalDivider(
width: 20,
thickness: 1,
color: Colors.black,
indent: 30,
endIndent: 10,
),
SizedBox(
width: 55,
child: TextFormField(
maxLength: 7,
initialValue: '0',
onChanged: (val) {
setState(() {
_onIngredientUpdate(key, quantity: val);
});
},
),
),
Padding(padding: EdgeInsets.only(left: 10)),
DropdownButton(
hint: Text('pcs'),
items: ['pcs', 'ml', 'g'].map(
(val) {
return DropdownMenuItem<String>(
value: val,
child: Text(val),
);
},
).toList(),
onChanged: (val) {
setState(() {
_onIngredientUpdate(key,measurement: val.toString());
});
},
)
],
),
);
}
_onIngredientUpdate(int key, {String? name, String? measurement, String? quantity}) {
int foundKey = -1;
_ingredientsValues.forEach((element) {
if (element.id.contains(key.toString())) {
foundKey = key;
}
});
if (-1 != foundKey) {
_ingredientsValues.removeWhere((map) {
return map.id == foundKey.toString();
});
}
Map<String, dynamic> json = {'id': key, 'name': name, 'measurement': measurement, 'quantity':quantity};
_ingredientsValues.add(json as Ingredient);
}
_preparationStepRow(int key) {
return IntrinsicHeight(
child: Row(
children: [
Padding(padding: EdgeInsets.only(left: 10)),
SizedBox(
width: 225,
height: 50,
child: TextFormField(
maxLength: 35,
onChanged: (val) => {
_onPreparationUpdate(key,val)
},
),
),
],
),
);
}
_onPreparationUpdate(int key, String val) {
int foundKey = -1;
_preparationStepsValues.forEach((element) {
if (element.id.contains(key.toString())) {
foundKey = key;
}
});
if (-1 != foundKey) {
_preparationStepsValues.removeWhere((map) {
return map.id == foundKey.toString();
});
}
Map<String, dynamic> json = {'id': key, 'step': val};
_preparationStepsValues.add(json as PreparationStep);
}
}
Issue GIF:
EDIT:
Issue is not related with form. I have replaced whole form with only one field without any logic and issue remains.
It is probably related to named routes.
As I was thinking, issue was related with usage of named routes.
I managed to bypass this issue with using Future.delayed and pushNamedAndRemoveUntil
In main_menu_screen I have created method which I later used to redirect to categories.
void redirectToCategory(BuildContext context, String categoryName) {
Future.delayed(Duration.zero, () {
Navigator.pushNamedAndRemoveUntil(
context,
'/recipeScreen',
(_) => false,
arguments: BlocProvider.value(
value: BlocProvider.of<RecipesBloc>(context)
..add(LoadRecipesEvent())
..category = categoryName,
child: RecipesScreen(),
),
);
});
I created a database with sqflite on the user's phone. The words entered by the user are saved in the main list.
When you press the icon next to it, it is added to the favorite list, but when the user exits the application, the favorite list is reset.
The main list is the same, there is no problem with it.
When a word is deleted from the main list, it is also deleted from the favorite. But the only problem is that when the favorite list comes out and enters, it resets and writes blank.
How can I make the favorite list stay the same when I exit the application?
This is home page dart file.
class WordList extends StatefulWidget {
const WordList({Key key}) : super(key: key);
#override
State<StatefulWidget> createState() {
return _WordListState();
}
}
class _WordListState extends State {
var dbHelper = DbHelper();
List<Word> words;
List<Word> favoriteWords = [];
int wordCount = 0;
int fwordCount = 0;
#override
void initState() {
getWords();
}
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
titleSpacing: 0,
title: Text(
"ShopList",
style: GoogleFonts.caveat(
textStyle: const TextStyle(
color: Colors.white,
fontSize: 35,
letterSpacing: 1,
fontWeight: FontWeight.w700,
),
),
),
leading: const Padding(
padding: EdgeInsets.all(2.0),
child: Icon(
Icons.shopping_cart,
size: 35.0,
),
),
backgroundColor: Colors.deepPurple,
bottom: const TabBar(
indicatorColor: Colors.deepPurpleAccent,
automaticIndicatorColorAdjustment: false,
labelColor: Colors.deepPurple,
unselectedLabelColor: Colors.white,
indicatorSize: TabBarIndicatorSize.label,
indicator: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(7), topRight: Radius.circular(7)),
color: Colors.white),
tabs: [
Tab(
child: Align(
alignment: Alignment.center,
child: Icon(Icons.article_rounded),
),
),
Tab(
child: Align(
alignment: Alignment.center,
child: Icon(Icons.favorite),
),
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
goToWordAdd();
},
child: const Icon(Icons.add),
tooltip: "Add New Item",
splashColor: Colors.white,
backgroundColor: Colors.deepPurple,
),
body: TabBarView(
children: [
ListView.builder(
itemCount: wordCount,
itemBuilder: (BuildContext context, int position) {
return Card(
child: Row(
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.all(3.0),
child: ListTile(
title: SelectableText(
words[position].word,
cursorColor: Colors.purple,
showCursor: false,
toolbarOptions: const ToolbarOptions(
copy: true,
selectAll: true,
cut: false,
paste: false),
style: GoogleFonts.caveat(
textStyle: const TextStyle(
color: Colors.deepPurple,
fontSize: 25.0,
fontWeight: FontWeight.w700,
),
),
),
subtitle: SelectableText(
words[position].description,
cursorColor: Colors.purple,
showCursor: false,
toolbarOptions: const ToolbarOptions(
copy: true,
selectAll: true,
cut: false,
paste: false),
style: GoogleFonts.caveat(
textStyle: const TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.w700,
),
),
),
),
),
),
ElevatedButton(
onPressed: () {
setState(() {
if (!favoriteWords
.contains(words[position])) {
favoriteWords.add(words[position]);
}
});
},
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all<Color>(
Colors.deepPurple,
),
shape: MaterialStateProperty.all<
RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(5.0),
side: const BorderSide(
color:
Colors.deepPurpleAccent)))),
child: const Icon(
Icons.favorite,
color: Colors.white,
),
),
IconButton(
color: Colors.blueGrey,
icon: const Icon(Icons.delete),
tooltip: 'Delete Item',
onPressed: () {
goToDelete(words[position]);
},
),
],
),
);
},
),
favoriteWords.isEmpty
? const Center(
child: Text(
'Ürünlerini favorilerine ekle, almayı unutma! ',
style: TextStyle(
color: Colors.deepPurple,
fontWeight: FontWeight.bold),
),
)
: ListView.builder(
itemCount: fwordCount,
itemBuilder: (BuildContext context, int index) {
return Card(
child: Row(
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.all(3.0),
child: ListTile(
title: SelectableText(
favoriteWords[index].word,
cursorColor: Colors.purple,
showCursor: false,
toolbarOptions: const ToolbarOptions(
copy: true,
selectAll: true,
cut: false,
paste: false),
style: const TextStyle(fontSize: 17.0),
),
subtitle: SelectableText(
favoriteWords[index].description,
cursorColor: Colors.purple,
showCursor: false,
toolbarOptions: const ToolbarOptions(
copy: true,
selectAll: true,
cut: false,
paste: false),
style: const TextStyle(fontSize: 17.0),
),
),
),
),
ElevatedButton(
onPressed: () {
setState(() {
favoriteWords.remove(favoriteWords[index]);
});
},
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all<Color>(
Colors.deepPurple,
),
),
child: const Icon(
Icons.remove,
color: Colors.white,
),
),
],
),
);
},
),
],
),
),
);
}
void goToWordAdd() async {
bool result = await Navigator.push(
context, MaterialPageRoute(builder: (context) => const WordAdd()));
if (result != null) {
if (result) {
getWords();
}
}
}
void getWords() {
var wordsFuture = dbHelper.getWords();
wordsFuture.then((data) {
setState(() {
words = data;
wordCount = data.length;
});
});
}
void goToDelete(Word word) async {
await dbHelper.delete(word.id);
favoriteWords.remove(word);
getWords();
}
}
I am trying to build a social media app using flutter, i have created an sign in page and login page in sign in page it takes userAvatar,
Username,Useremail,UserPassword too . when clicking on floating action button as a submit button it will register the account but in my case it only register the email,useruid,username and userpassord but not userimage it shows this'package:flutter/src/paintings/_network_image_io.dart':Failed assertion: line 25 pros 14: 'url != null': is not true.The relevant error causing widget was stream builder...this is my error .. can any one help
i will leave my code below.
LandingServices as a sign in and log in
class LandingService with ChangeNotifier {
TextEditingController userEmailController = TextEditingController();
TextEditingController userNameController = TextEditingController();
TextEditingController userPasswordController = TextEditingController();
ConstantColors constantColors = ConstantColors();
showUserAvatar
showUserAvatar(BuildContext context) {
return showModalBottomSheet(
context: context,
builder: (context) {
return Container(
height: MediaQuery.of(context).size.height * 0.36,
width: MediaQuery.of(context).size.width,
child: Column(
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 150.0),
child: Divider(
thickness: 4.0,
color: constantColors.whiteColor,
),
),
CircleAvatar(
radius: 69.0,
backgroundColor: constantColors.transperant,
backgroundImage: FileImage(
Provider.of<LandingUtils>(context, listen: false).userAvatar
)),
Container(
child:
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
MaterialButton(
child: Text(
'Reselect',
style: TextStyle(
color: constantColors.whiteColor,
fontWeight: FontWeight.bold,
decoration: TextDecoration.underline,
decorationColor: constantColors.whiteColor),
),
onPressed: () {
Provider.of<LandingUtils>(context, listen: false)
.pickUserAvatar(context, ImageSource.gallery);
}),
MaterialButton(
color: constantColors.blueColor,
child: Text(
'Confirm Image',
style: TextStyle(
color: constantColors.whiteColor,
fontWeight: FontWeight.bold,
),
),
onPressed: () {
Provider.of<FirebaseOperations>(context,
listen: false)
.uploadUserAvatar(context)
.whenComplete(() {
signInSheet(context);
});
}),
],
),
)
],
),
decoration: BoxDecoration(
color: constantColors.blueGreyColor,
borderRadius: BorderRadius.circular(15.0),
),
);
});
}
passswordLessSignIn
Widget passswordLessSignIn(BuildContext context) {
return SizedBox(
height: MediaQuery.of(context).size.height * 0.40,
width: MediaQuery.of(context).size.width,
child: StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance.collection('users').snapshots(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(
child: CircularProgressIndicator(),
);
} else {
return new ListView(
children:
snapshot.data.docs.map((DocumentSnapshot documentSnapshot) {
return ListTile(
trailing: IconButton(
icon: Icon(FontAwesomeIcons.trashAlt,
color: constantColors.redColor),
onPressed: () {},
),
leading: CircleAvatar(
backgroundColor: constantColors.transperant,
backgroundImage:
NetworkImage(documentSnapshot.data()['userimage']),
),
subtitle: Text(documentSnapshot.data()['useremail'],
style: TextStyle(
fontWeight: FontWeight.bold,
color: constantColors.greenColor,
fontSize: 12.0)),
title: Text(documentSnapshot.data()['username'],
style: TextStyle(
fontWeight: FontWeight.bold,
color: constantColors.greenColor)),
);
}).toList());
}
},
),
);
}
signInSheet
signInSheet(BuildContext context) {
return showModalBottomSheet(
context: context,
isScrollControlled: true,
builder: (context) {
return Padding(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom),
child: Container(
height: MediaQuery.of(context).size.height * 0.5,
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
color: constantColors.blueGreyColor,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(12.0),
topRight: Radius.circular(12.0))),
child: Column(
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 150.0),
child: Divider(
thickness: 4.0,
color: constantColors.whiteColor,
),
),
CircleAvatar(
backgroundImage: FileImage(
Provider.of<LandingUtils>(context, listen: false)
.getUserAvatar),
backgroundColor: constantColors.redColor,
radius: 60.0,
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: TextField(
controller: userNameController,
decoration: InputDecoration(
hintText: 'Enter name...',
hintStyle: TextStyle(
color: constantColors.whiteColor,
fontWeight: FontWeight.bold,
fontSize: 16.0,
),
),
style: TextStyle(
color: constantColors.whiteColor,
fontWeight: FontWeight.bold,
fontSize: 18.0,
),
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: TextField(
controller: userEmailController,
decoration: InputDecoration(
hintText: 'Enter Email...',
hintStyle: TextStyle(
color: constantColors.whiteColor,
fontWeight: FontWeight.bold,
fontSize: 16.0,
),
),
style: TextStyle(
color: constantColors.whiteColor,
fontWeight: FontWeight.bold,
fontSize: 18.0,
),
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: TextField(
controller: userPasswordController,
decoration: InputDecoration(
hintText: 'Enter Password...',
hintStyle: TextStyle(
color: constantColors.whiteColor,
fontWeight: FontWeight.bold,
fontSize: 16.0,
),
),
style: TextStyle(
color: constantColors.whiteColor,
fontWeight: FontWeight.bold,
fontSize: 18.0,
),
),
),
Padding(
padding: const EdgeInsets.only(top: 0.32),
child: FloatingActionButton(
backgroundColor: constantColors.redColor,
child: Icon(
FontAwesomeIcons.check,
color: constantColors.whiteColor,
),
onPressed: () {
if (userEmailController.text.isNotEmpty) {
Provider.of<Authentication>(context, listen: false)
.createAccount(userEmailController.text,
userPasswordController.text)
.whenComplete(() {
print('Creating collections...');
Provider.of<FirebaseOperations>(context,
listen: false)
.createUserCollection(context, {
'useruid': Provider.of<Authentication>(context,
listen: false)
.getUserUid,
'useremail': userEmailController.text,
'username': userNameController.text,
'userimage': Provider.of<LandingUtils>(context,
listen: false)
.getUserAvatarUrl,
});
}).whenComplete(() {
Navigator.pushReplacement(
context,
PageTransition(
child: Homepage(),
type: PageTransitionType.bottomToTop));
});
} else {
warningText(context, 'Fill all the data!');
}
}),
),
],
),
),
);
});
}
firebaseOperation.dart
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:theGupshup/screens/LandingPage/LandingUtils.dart';
import 'package:theGupshup/services/Authentication.dart';
class FirebaseOperations with ChangeNotifier {
UploadTask imageUploadTask;
String initUserName, initUserEmail, initUserImage;
String get getInitUserName => initUserName;
String get getInitUserEmail => initUserEmail;
String get getInitUserImage => initUserImage;
Future uploadUserAvatar(BuildContext context) async {
Reference imageReference = FirebaseStorage.instance.ref().child(
'userProfileAvatar/${Provider.of<LandingUtils>(context, listen:
false).getUserAvatar.path}/${TimeOfDay.now()}');
imageUploadTask = imageReference.putFile(
Provider.of<LandingUtils>(context, listen: false).getUserAvatar);
await imageUploadTask.whenComplete(() {
print('Image uploaded!');
});
imageReference.getDownloadURL().then((url) {
Provider.of<LandingUtils>(context, listen: false).userAvatarUrl =
url.toString();
print(
'the user profile avatar url => ${Provider.of<LandingUtils>(context, listen:
false).userAvatarUrl}');
notifyListeners();
});
}
Future createUserCollection(BuildContext context, dynamic data) async {
return FirebaseFirestore.instance
.collection('users')
.doc(Provider.of<Authentication>(context, listen: false).getUserUid)
.set(data);
}
Future initUserData(BuildContext context) async {
return FirebaseFirestore.instance
.collection('users')
.doc(Provider.of<Authentication>(context, listen: false).getUserUid)
.get()
.then((doc) {
print('Fetching user data');
initUserName = doc.data()['username'];
initUserEmail = doc.data()['useremail'];
initUserImage = doc.data()['userimage'];
print(initUserName);
print(initUserEmail);
print(initUserImage);
notifyListeners();
});
}
}
Landing utils.dart
class LandingUtils with ChangeNotifier {
ConstantColors constantColors = ConstantColors();
final picker = ImagePicker();
File userAvatar;
File get getUserAvatar => userAvatar;
String userAvatarUrl;
String get getUserAvatarUrl => userAvatarUrl;
Future pickUserAvatar(BuildContext context, ImageSource source) async {
final pickedUserAvatar = await picker.getImage(source: source);
pickedUserAvatar == null
? print('Select image')
: userAvatar = File(pickedUserAvatar.path);
print(userAvatar.path);
userAvatar != null
? Provider.of<LandingService>(context, listen: false)
.showUserAvatar(context)
: print('Image Upload error');
notifyListeners();
}
Future selectAvatarOptionSheet(BuildContext context) async {
return showModalBottomSheet(
context: context,
builder: (context) {
return Container(
child: Column(
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 150.0),
child: Divider(
thickness: 4.0,
color: constantColors.whiteColor,
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
MaterialButton(
color: constantColors.blueColor,
child: Text('Gallery',
style: TextStyle(
color: constantColors.whiteColor,
fontWeight: FontWeight.bold,
fontSize: 18.0)),
onPressed: () {
pickUserAvatar(context, ImageSource.gallery)
.whenComplete(() {
Navigator.pop(context);
Provider.of<LandingService>(context, listen: false)
.showUserAvatar(context);
});
}),
MaterialButton(
color: constantColors.blueColor,
child: Text('Camera',
style: TextStyle(
color: constantColors.whiteColor,
fontWeight: FontWeight.bold,
fontSize: 18.0)),
onPressed: () {
pickUserAvatar(context, ImageSource.camera)
.whenComplete(() {
Navigator.pop(context);
Provider.of<LandingService>(context, listen: false)
.showUserAvatar(context);
});
}),
],
),
],
),
height: MediaQuery.of(context).size.height * 0.1,
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
color: constantColors.blueGreyColor,
borderRadius: BorderRadius.circular(12.0)),
);
});
}
}
can any one help the error pic is below
Can any one help
In your passwordLessSignIn page try giving a default image to circle avatar when the userimage is null -
Example -
leading: CircleAvatar(
backgroundColor: constantColors.transperant,
backgroundImage:
NetworkImage(documentSnapshot.data()['userimage'] ?? "https://i.guim.co.uk/img/media/7a633730f5f90db3c12f6efc954a2d5b475c3d4a/0_138_5544_3327/master/5544.jpg?width=1200&height=1200&quality=85&auto=format&fit=crop&s=27c09d27ccbd139fd0f7d1cef8f7d41d"),
),
User Entered Data is not saved on Firebase_realtime_database.I tried making a personal information form . But when I click on submit button , the data entred by user is not saving in firebase(real-time database). What could be error?
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:intl/intl.dart';
import 'package:firebase_database/firebase_database.dart';
class DonorRegistration extends StatefulWidget {
#override
DonorRegistration({Key key}) : super(key: key);
#override
_DonorRegistrationState createState() => _DonorRegistrationState();
}
}
class _DonorRegistrationState extends State<DonorRegistration> {
var data;
bool autoValidate = true;
bool readOnly = false;
bool showSegmentedControl = true;
final GlobalKey<FormBuilderState> _fbKey = GlobalKey<FormBuilderState>();
final ValueChanged _onChanged = (val) => print(val);
var currentItemSelected3;
bool disabledropdown = true;
final TextEditingController _nameController = TextEditingController();
String _gender = 'Male';
final TextEditingController _ageController = TextEditingController();
final dbRef = FirebaseDatabase.instance.reference().child("donor");
This is UI area
enter code here
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Color.fromRGBO(1500, 0, 5, 1),
title: Text('Donor Registration'),
),
body: Padding(
padding: const EdgeInsets.all(10),
child: ListView(
children: <Widget>[
Container(
height: 100,
width: 100,
child: CircleAvatar(
backgroundColor: Colors.transparent,
radius: 65.0,
child: Image.asset('lib/assets/logo.png'))),
FormBuilder(
// context,
key: _fbKey,
// autovalidate: true,
readOnly: false,
child: Column(
children: <Widget>[
Text('Personal Information'),
SizedBox(height: 15),
FormBuilderTextField(
attribute: 'Name',
controller: _nameController,
decoration: const InputDecoration(
border: OutlineInputBorder(),
icon: Icon(
Icons.account_circle,
color: Color.fromRGBO(255, 0, 0, 1),
),
labelText: 'Full Name',
hintText: 'Enter Your Full name',
),
validators: [
FormBuilderValidators.required(
errorText: 'This field required')
],
keyboardType: TextInputType.name,
//controller: _nameController,
),
SizedBox(height: 25),
FormBuilderRadioGroup(
attribute: 'radio_group',
decoration: const InputDecoration(
//value: gender,
border: OutlineInputBorder(),
icon: Icon(
Icons.person_pin,
color: Color.fromRGBO(255, 0, 0, 1),
),
labelText: 'Gender'),
onChanged: _onChanged,
options: [
FormBuilderFieldOption(value: 'M', child: Text('Male')),
FormBuilderFieldOption(value: 'F', child: Text('Female')),
FormBuilderFieldOption(value: 'O', child: Text('Other')),
]
.map((_gender) => FormBuilderFieldOption(
value: _gender,
child: Text('$_gender'),
))
.toList(growable: false),
validators: [
FormBuilderValidators.required(
errorText: 'This field required')
],
),
SizedBox(height: 15),
FormBuilderTextField(
attribute: 'age',
// autovalidate: true,
controller: _ageController,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Age',
icon: Icon(
Icons.confirmation_number,
color: Color.fromRGBO(255, 0, 0, 1),
),
),
validators: [
FormBuilderValidators.required(
errorText: 'This field required')
],
keyboardType: TextInputType.number,
),
FormBuilderSwitch(
label: Text('I Accept the tems and conditions'),
attribute: 'accept_terms_switch',
initialValue: true,
onChanged: _onChanged,
),
SizedBox(height: 15),
],
),
),
Row(
children: <Widget>[
Expanded(
child: MaterialButton(
color: Theme.of(context).accentColor,
child: Text(
'Submit',
style: TextStyle(color: Colors.white),
),
onPressed: () {
if (_fbKey.currentState.validate()) {
dbRef.push().set({
"name": _nameController.text,
"age": _ageController.text,
"gender": _gender,
"disease": _diseaseController.text,
"blood_group": _blood,
"body_part": _donate,
"Hospitals": _hospital,
}).then((_) {
Scaffold.of(context).showSnackBar(
SnackBar(content: Text('Successfully Added')));
_ageController.clear();
_nameController.clear();
}).catchError((onError) {
Scaffold.of(context)
.showSnackBar(SnackBar(content: Text(onError)));
});
} else {
print(_fbKey.currentState.value);
print('validation failed');
}
},
),
),
SizedBox(width: 20),
Expanded(
child: MaterialButton(
color: Theme.of(context).accentColor,
child: Text(
'Reset',
style: TextStyle(color: Colors.white),
),
onPressed: () {
_fbKey.currentState.reset();
},
)),
],
),
],
),
),
);
}
#override
void dispose() {
super.dispose();
_ageController.dispose();
_nameController.dispose();
}
}
please tell me what could be errors.
**Hello I am using flutter and querySnapshot in my code with document but i dont understand whats error anyone help me how i fix this error below my code .......................................................................................................................................................................... **
dd.dart
class SearchPage extends StatefulWidget {
#override
_SearchPageState createState() => _SearchPageState();
}
class _SearchPageState extends State<SearchPage>
with AutomaticKeepAliveClientMixin<SearchPage> {
TextEditingController searchTextEditingController = TextEditingController();
Future<QuerySnapshot> futureSearchResults;
emptyTheTextFormField() {
searchTextEditingController.clear();
}
controllSearching(String str) {
Future<QuerySnapshot> allUsers = userRefrence
.where("profileName", isGreaterThanOrEqualTo: str)
.getDocuments();
setState(() {
futureSearchResults = allUsers;
});
}
Container displayNoSearchResult() {
final Orientation orientation = MediaQuery.of(context).orientation;
return Container(
child: Center(
child: ListView(
shrinkWrap: true,
children: <Widget>[
Icon(
Icons.group,
color: Colors.grey,
size: 200.0,
),
Icon(
Icons.search,
color: Colors.grey,
size: 20.0,
),
Text(
"Search Users",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w500,
fontSize: 65.0),
),
],
),
),
);
}
displayUsersFoundScreen() {
return FutureBuilder(
future: futureSearchResults,
builder: (context, dataSnapshot) {
if (dataSnapshot.hasData) {
return circularProgress();
}
List<UserResult> searchUserResult = [];
dataSnapshot.data.document.forEach((document) {
User eachuser = User.fromDocument(document);
UserResult userResult = UserResult(eachuser);
searchUserResult.add(userResult);
});
return ListView(children: searchUserResult);
},
);
}
AppBar searchPageHeader() {
return AppBar(
backgroundColor: Colors.black,
title: TextFormField(
style: TextStyle(fontSize: 18.0, color: Colors.white),
controller: searchTextEditingController,
decoration: InputDecoration(
hintText: "Search Here....",
hintStyle: TextStyle(color: Colors.grey),
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.grey),
),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.white),
),
filled: true,
prefixIcon: Icon(Icons.person_pin, color: Colors.white, size: 30.0),
suffixIcon: IconButton(
icon: Icon(
Icons.clear,
color: Colors.white,
),
onPressed: emptyTheTextFormField),
),
onFieldSubmitted: controllSearching,
),
);
}
bool get wantKeepAlive => true;
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
appBar: searchPageHeader(),
body: futureSearchResults == null
? displayNoSearchResult()
: displayUsersFoundScreen(),
);
}
}
class UserResult extends StatelessWidget {
final User eachuser;
UserResult(this.eachuser);
#override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(3.0),
child: Container(
color: Colors.white54,
child: Column(
children: <Widget>[
GestureDetector(
onTap: () => print("tapped"),
child: ListTile(
leading: CircleAvatar(
backgroundColor: Colors.black,
backgroundImage: CachedNetworkImageProvider(eachuser.url),
),
title: Text(
eachuser.profileName,
style: TextStyle(
color: Colors.black,
fontSize: 16.0,
fontWeight: FontWeight.bold),
),
subtitle: Text(
eachuser.username,
style: TextStyle(
color: Colors.black,
fontSize: 13.0,
),
),
),
)
],
)),
);
}
}
You are getting the error because of your if condition, it should be if (!dataSnapshot.hasData) {...}.
Replace:
if (dataSnapshot.hasData) {...}
with
if (!dataSnapshot.hasData){...}.
I added a fix using your code:
displayUsersFoundScreen() {
return FutureBuilder(
future: futureSearchResults,
builder: (context, dataSnapshot) {
if (!dataSnapshot.hasData) { // should be !dataSnapshot.hasData
return circularProgress();
}
List<UserResult> searchUserResult = [];
dataSnapshot.data.document.forEach((document) {
User eachuser = User.fromDocument(document);
UserResult userResult = UserResult(eachuser);
searchUserResult.add(userResult);
});
return ListView(children: searchUserResult);
},
);
}