type 'Null' is not a subtype of type 'File' of 'image' flutter problem - flutter

I uploaded my image to FireStore. When I am creating an image it's perfectly ok everything uploading perfectly. After SignUp I can easily go to the user profile and can see the user name and email. But when I log out from the user profile and from my LOGIN from when providing existing email and password which I have created already then the Exception is thrown. I am not getting the issue. Exception has occurred.
_TypeError (type 'Null' is not a subtype of type 'File' of 'image')
import 'dart:io';
import '../picker/user_image_picker.dart';
import 'package:flutter/material.dart';
class AuthForm extends StatefulWidget {
AuthForm(this.submitFn, this.isLoading);
final bool isLoading;
var submitFn;
void function(
String email,
String password,
String userName,
File image,
bool isLogin,
BuildContext ctx,
);
#override
_AuthFormState createState() => _AuthFormState();
#override
noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
}
class _AuthFormState extends State<AuthForm> {
final _formKey = GlobalKey<FormState>();
var _isLogin = true;
var _userEmail = '';
var _userName = '';
var _userPasssword = '';
File? userImageFile;
void pickedImage(File image) {
userImageFile = image;
}
void _trySubmit() {
final isValid = _formKey.currentState!.validate();
FocusScope.of(context).unfocus();
if (userImageFile == null && !_isLogin) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Please Pick an Image.'),
backgroundColor: Theme.of(context).errorColor,
),
);
return;
}
if (isValid) {
_formKey.currentState?.save();
print(_userEmail);
print(_userName);
print(_userPasssword);
print(' Good to go ');
widget.submitFn(
_userEmail.trim(),
_userPasssword.trim(),
_userName.trim(),
userImageFile,
_isLogin,
context,
);
} else {
print('Form is not valid');
}
}
#override
Widget build(BuildContext context) {
return Card(
margin: EdgeInsets.all(20),
child: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.all(16),
child: Form(
key: _formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
if (!_isLogin) UserImagePicker(pickedImage),//this is my image file
TextFormField(
key: ValueKey('email'),
onSaved: (value) {
_userEmail = value!;
},
validator: (value) {
if (value!.isEmpty ||
!value.contains(RegExp(
'^[a-zA-Z0-9+_.-]+#[a-zA-Z0-9.-]+.[a-z]+.[com]'))) {
return 'enter valid Email';
//print('Email validation is not ok');
} else {
return null;
}
},
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
labelText: 'Email Address', icon: Icon(Icons.email)),
),
if (!_isLogin)
TextFormField(
key: ValueKey('userName'),
onSaved: (value) {
_userName = value!;
},
validator: (value) {
if (value == null || value.length < 4) {
return 'Enter At least 4 charaters ';
}
return null;
},
decoration: InputDecoration(
labelText: 'User Name', icon: Icon(Icons.person)),
),
TextFormField(
key: ValueKey('password'),
onSaved: (value) {
_userPasssword = value!;
},
obscureText: true,
validator: (value) {
if (value == null || value.isEmpty || value.length < 7) {
return 'Enter at least 7 Digits';
}
return null;
},
decoration: InputDecoration(
labelText: 'Password',
icon: Icon(
Icons.security,
),
),
),
SizedBox(
height: 20,
),
if (widget.isLoading) CircularProgressIndicator(),
if (!widget.isLoading)
ElevatedButton(
child: Text(_isLogin ? 'Login' : 'Signup'),
onPressed: _trySubmit,
),
if (widget.isLoading) CircularProgressIndicator(),
if (!widget.isLoading)
TextButton(
style: TextButton.styleFrom(
primary: Theme.of(context).primaryColor,
),
child: Text(_isLogin
? 'Create New Account'
: 'I already have an account'),
onPressed: () {
setState(
() {
_isLogin = !_isLogin;
},
);
},
)
],
),
),
),
),
);
}
}

Looks like userImageFile is null. This happen because this variable is nullable, and when it gets passed to submitFn (which weirdly is a dynamic variable...?) it throws, because it expects a non-nullable image parameter.

Related

I am new to programming can someone help me what's the problem here, I was doing a login page and this happens

If password and username is same, I want to print 'username and password is same' statement in the terminal .But it is only printing the second statement 'username and password does not match even if username and password is same or not . I don't understand why this happened somebody help, I am new here' ( NB : problem is inside the function named checkLogin)
class ScreenLogin extends StatefulWidget {
ScreenLogin({Key? key}) : super(key: key);
#override
State<ScreenLogin> createState() => _ScreenLoginState();
}
class _ScreenLoginState extends State<ScreenLogin> {
final _usernameController = TextEditingController();
final _passwordController = TextEditingController();
bool _isDataMatched = false;
final _formkey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Padding(
padding: const EdgeInsets.all(15.0),
child: Form(
key: _formkey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
TextFormField(
controller: _usernameController,
decoration: const InputDecoration(
border: OutlineInputBorder(), hintText: 'Username'),
validator: (value) {
if (value == null || value.isEmpty) {
return 'value is empty';
} else {
return null;
}
},
),
const SizedBox(
height: 20,
),
TextFormField(
controller: _passwordController,
obscureText: true,
decoration: const InputDecoration(
border: OutlineInputBorder(), hintText: 'Password'),
validator: (value) {
if (value == null || value.isEmpty) {
return 'value is empty';
} else {
return null;
}
}),
SizedBox(
height: 20,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Visibility(
visible: _isDataMatched,
child: Text(
'Username and password does not match',
style: TextStyle(color: Colors.red),
),
),
ElevatedButton.icon(
onPressed: () {
if (_formkey.currentState!.validate()) {
checkLogin(context);
} else {
print('Data Empty');
}
},
icon: const Icon(Icons.check),
label: const Text('Login ')),
],
)
],
),
),
),
));
}
void checkLogin(BuildContext context) {
final _username = _usernameController;
final _password = _passwordController;
if (_password == _username) {
print('Username and password is matching');
} else {
print('Username and password does not match');
}
}
}
To get text, you need to use .text on controller.
_usernameController.text;
void checkLogin(BuildContext context) {
final _username = _usernameController.text;
final _password = _passwordController.text;
if (_password == _username) {
print('Username and password is matching');
} else {
print('Username and password does not match');
}
}
In login check you should do this:
void checkLogin(BuildContext context) {
final _username = _usernameController.text;
final _password = _passwordController.text;
if (_password == _username) {
print('Username and password is matching');
} else {
print('Username and password does not match');
}
}

How to validate textfield when posting to firestore in flutter? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 11 months ago.
Improve this question
I have added validator in TextField but validator is not working while submitting data. Save button saves the data with null value.
import 'package:cloud_firestore/cloud_firestore.dart';
import '../../screens/orders/order_success.dart';
import '../../services/global_methods.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
class PlaceOrder extends StatefulWidget {
static const routeName = '/place-order';
const PlaceOrder({Key? key}) : super(key: key);
#override
State<PlaceOrder> createState() => _PlaceOrderState();
}
class _PlaceOrderState extends State<PlaceOrder> {
final _formKey = GlobalKey<FormState>();
String? _name;
int? _phoneNumber;
String? _fullAddress;
String? _area;
String? _city;
String? _addressType;
final TextEditingController _addressController = TextEditingController();
String? _addressValue;
String? _deliverySlotValue;
final FirebaseAuth _auth = FirebaseAuth.instance;
late bool _isLoading = false;
final GlobalMethods _globalMethods = GlobalMethods();
final FocusNode _numberFocusNode = FocusNode();
#override
void initState() {
setState(() {
_isLoading = false;
});
super.initState();
}
#override
void dispose() {
_numberFocusNode.dispose();
super.dispose();
}
void _submitData() async {
final _isValid = _formKey.currentState!.validate();
FocusScope.of(context).unfocus();
if (_isValid) {
_formKey.currentState!.save();
}
try {
setState(() {
_isLoading = true;
});
final User? user = _auth.currentUser;
final _uid = user!.uid;
final orderId = ModalRoute.of(context)!.settings.arguments as String;
FirebaseFirestore.instance
.collection('orders')
.doc(orderId)
.set({
'userId': _uid,
'name': _name,
'phoneNumber': _phoneNumber,
'addressType': _addressType,
'address': _fullAddress,
'area': _area,
'city': _city,
'deliverySlot': _deliverySlotValue,
}, SetOptions(merge: true));
} catch (error) {
_globalMethods.authDialog(context, error.toString());
} finally {
setState(() {
_isLoading = false;
});
Navigator.of(context).pushReplacementNamed(OrderSuccess.routeName);
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Add new address'),
),
body: Form(
key: _formKey,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Row(
children: [
DropdownButton<String>(
items: const [
DropdownMenuItem<String>(
child: Text('Home'),
value: 'Home',
),
DropdownMenuItem<String>(
child: Text('Office'),
value: 'Office',
),
DropdownMenuItem<String>(
child: Text('Other'),
value: 'Other',
),
],
onChanged: (value) {
setState(() {
_addressValue = value.toString();
_addressController.text = value.toString();
print(_addressType);
});
},
hint: const Text('Select address type'),
value: _addressValue,
),
const SizedBox(
width: 10,
),
Expanded(
child: TextFormField(
key: const ValueKey('addressType'),
controller: _addressController,
validator: (val) {
if (val!.isEmpty) {
return 'Please select address type';
}
return null;
},
decoration: const InputDecoration(
labelText: 'Select your address type',
),
onSaved: (val) {
_addressType = val.toString();
},
),
),
],
),
TextFormField(
onSaved: (value) {
_name = value!;
},
textInputAction: TextInputAction.next,
key: const ValueKey('name'),
validator: (value) {
if (value!.isEmpty) {
return 'Please enter your name';
}
return null;
},
decoration: InputDecoration(
labelText: 'Name',
filled: true,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
),
prefixIcon: const Icon(Icons.location_city),
),
),
const SizedBox(height: 8),
TextFormField(
onSaved: (value) {
_fullAddress = value!;
},
textInputAction: TextInputAction.next,
key: const ValueKey('streetAddress'),
validator: (value) {
if (value!.isEmpty) {
return 'Please enter your address';
}
return null;
},
decoration: InputDecoration(
labelText: 'Address',
filled: true,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
),
prefixIcon: const Icon(Icons.location_city),
),
),
const SizedBox(height: 8),
TextFormField(
onSaved: (value) {
_area = value!;
},
textInputAction: TextInputAction.next,
key: const ValueKey('area'),
validator: (value) {
if (value!.isEmpty) {
return 'Please enter your area';
}
return null;
},
decoration: InputDecoration(
labelText: 'Area',
filled: true,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
),
prefixIcon: const Icon(Icons.location_city),
),
),
const SizedBox(height: 8),
TextFormField(
onSaved: (value) {
_city = value!;
},
textInputAction: TextInputAction.next,
key: const ValueKey('city'),
validator: (value) {
if (value!.isEmpty) {
return 'Please enter your city';
}
return null;
},
decoration: InputDecoration(
labelText: 'City',
filled: true,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
),
prefixIcon: const Icon(Icons.location_city),
),
),
const SizedBox(height: 8),
TextFormField(
onSaved: (value) {
_phoneNumber = int.parse(value!);
},
textInputAction: TextInputAction.next,
// keyboardType: TextInputType.emailAddress,
onEditingComplete: () =>
FocusScope.of(context).requestFocus(_numberFocusNode),
key: const ValueKey('number'),
validator: (value) {
if (value!.length < 10) {
return 'Phone number must be 10 units';
}
return null;
},
decoration: InputDecoration(
labelText: 'Phone Number',
filled: true,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
),
prefixIcon: const Icon(Icons.phone),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
DropdownButton<String>(
items: const [
DropdownMenuItem<String>(
child: Text('11:00am to 1:00pm'),
value: '11:00am to 1:00pm',
),
DropdownMenuItem<String>(
child: Text('1:00pm to 3:00pm'),
value: '1:00pm to 3:00pm',
),
DropdownMenuItem<String>(
child: Text('3:00pm to 5:00pm'),
value: '3:00pm to 5:pm',
),
DropdownMenuItem<String>(
child: Text('5:00pm to 7:00pm'),
value: '5:00pm to 7:00pm',
),
DropdownMenuItem<String>(
child: Text('7:00pm to 9:pm'),
value: '7:00pm to 9:pm',
),
],
onChanged: (value) {
setState(() {
_deliverySlotValue = value.toString();
});
},
hint: const Text('Select Delivery Slot'),
value: _deliverySlotValue,
),
],
),
Padding(
padding: const EdgeInsets.all(48.0),
child: SizedBox(
child: ElevatedButton(
onPressed: _submitData,
child: _isLoading
? const CircularProgressIndicator()
: const Text(
'S U B M I T',
style: TextStyle(color: Colors.white),
),
),
),
),
],
),
),
),
),
);
}
}
It appears that the problem is a simple mistake with your control flow in the following code (see // comment):
void _submitData() async {
final _isValid = _formKey.currentState!.validate();
FocusScope.of(context).unfocus();
if (_isValid) {
_formKey.currentState!.save();
} // <----- this should not be here!
try {
setState(() {
_isLoading = true;
});
final User? user = _auth.currentUser;
final _uid = user!.uid;
final orderId = ModalRoute.of(context)!.settings.arguments as String;
FirebaseFirestore.instance
.collection('orders')
.doc(orderId)
.set({
'userId': _uid,
'name': _name,
'phoneNumber': _phoneNumber,
'addressType': _addressType,
'address': _fullAddress,
'area': _area,
'city': _city,
'deliverySlot': _deliverySlotValue,
}, SetOptions(merge: true));
} catch (error) {
_globalMethods.authDialog(context, error.toString());
} finally {
setState(() {
_isLoading = false;
});
Navigator.of(context).pushReplacementNamed(OrderSuccess.routeName);
}
}
As you can see, even if the user input is not valid, you still continue to upload the results to Firebase anyway.
Try correcting like this:
void _submitData() async {
final _isValid = _formKey.currentState!.validate();
FocusScope.of(context).unfocus();
if (_isValid) {
_formKey.currentState!.save();
try {
setState(() {
_isLoading = true;
});
final User? user = _auth.currentUser;
final _uid = user!.uid;
final orderId = ModalRoute.of(context)!.settings.arguments as String;
FirebaseFirestore.instance.collection('orders').doc(orderId).set({
'userId': _uid,
'name': _name,
'phoneNumber': _phoneNumber,
'addressType': _addressType,
'address': _fullAddress,
'area': _area,
'city': _city,
'deliverySlot': _deliverySlotValue,
}, SetOptions(merge: true));
} catch (error) {
_globalMethods.authDialog(context, error.toString());
} finally {
setState(() {
_isLoading = false;
});
Navigator.of(context).pushReplacementNamed(OrderSuccess.routeName);
}
} else {
// do nothing
}
}
The only possible reason is because of _addressType it's initial value is null
since it's a String? variable so if the user didn't select a "Delivery Slot"
the result of it after saving would be null,
what you need to do, it to check the value of _addressType if it's null or not then proceed to saving the form because your form doesn't check it if it's null or not.
You can add the form validator to the submit button itself. The below code works when you click on the submit button.
Padding(
padding: const EdgeInsets.all(48.0),
child: SizedBox(
child: ElevatedButton(
onPressed: (){
if (_formKey.currentState!.validate()){
_submitData;
}
},
child: _isLoading
? const CircularProgressIndicator()
: const Text(
'S U B M I T',
style: TextStyle(color: Colors.white),
),
),
),
),

The argument type 'string?' can't be assigned to the parameter type 'String"

What are the errors about this code? Please can you make it correct and send me the code?
4 positional argument(s) expected, but 2 found.
Try adding the missing arguments.
Undefined name '_formKey'.
Try correcting the name to one that is defined, or defining the name.
Undefined name '_authData'.
Try correcting the name to one that is defined, or defining the name.
Undefined name '_passwordController'.
Try correcting the name to one that is defined, or defining the name.
Undefined name '_passwordController'.
Try correcting the name to one that is defined, or defining the name.
The function '_submit' isn't defined.
Try importing the library that defines '_submit', correcting the name to the name of an existing function, or defining a function named '_submit'.
Expected a method, getter, setter or operator declaration.
This appears to be incomplete code. Try removing it or completing it.
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../models/authentication.dart';
import 'home_screen.dart';
import 'login_screen.dart';
class SignupScreen extends StatefulWidget {
static const routeName = '/signup';
#override
_SignupScreenState createState() => _SignupScreenState();
}
class _SignupScreenState extends State<SignupScreen> {
final GlobalKey<FormState> _formKey = GlobalKey();
TextEditingController _passwordController = new TextEditingController();
Map<String, String> _authData = {
'email' : '',
'password' : ''
};
void _showErrorDialog(String msg)
{
showDialog(
context: context,
builder: (ctx) => AlertDialog(
title: Text('An Error Occured'),
content: Text(msg),
actions: <Widget>[
FlatButton(
child: Text('Okay'),
onPressed: (){
Navigator.of(ctx).pop();
},
)
],
)
);
}
Future<void> _submit() async
{
if(!_formKey.currentState!.validate())
{
return;
}
_formKey.currentState!.save();
try{
var key = 'email';
await Provider.of<Authentication>(context, listen: false).signUp(
_authData[key],
_authData['password']
);
Navigator.of(context).pushReplacementNamed(HomeScreen.routeName);
} catch(error)
{
var errorMessage = 'Authentication Failed. Please try again later.';
_showErrorDialog(errorMessage);
}
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Signup'),
actions: <Widget>[
FlatButton(
child: Row(
children: <Widget>[
Text('Login'),
Icon(Icons.person)
],
),
textColor: Colors.white,
onPressed: (){
Navigator.of(context).pushReplacementNamed(LoginScreen.routeName);
},
)
],
),
body: Stack(
children: <Widget>[
Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Colors.limeAccent,
Colors.redAccent,
]
)
),
),
Center(
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
child: Container(
height: 300,
width: 300,
padding: EdgeInsets.all(16),
child: Form(
key: _formKey,
child: SingleChildScrollView(
child: Column(
children: <Widget>[
//email
TextFormField(
decoration: InputDecoration(labelText: 'Email'),
keyboardType: TextInputType.emailAddress,
validator: (value)
{
if(value!.isEmpty || !value.contains('#'))
{
return 'invalid email';
}
return null;
},
onSaved: (value)
{
_authData['email'] = value!;
},
),
//password
TextFormField(
decoration: InputDecoration(labelText: 'Password'),
obscureText: true,
controller: _passwordController,
validator: (value)
{
if(value!.isEmpty || value.length<=5)
{
return 'invalid password';
}
return null;
},
onSaved: (value)
{
_authData['password'] = value!;
},
),
//Confirm Password
TextFormField(
decoration: InputDecoration(labelText: 'Confirm Password'),
obscureText: true,
validator: (value)
{
if(value!.isEmpty || value != _passwordController.text)
{
return 'invalid password';
}
return null;
},
onSaved: (value)
{
},
),
SizedBox(
height: 30,
),
RaisedButton(
child: Text(
'Submit'
),
onPressed: ()
{
_submit();
},
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30),
),
color: Colors.blue,
textColor: Colors.white,
)
],
),
),
),
),
),
)
],
),
);
}
}
Image
You are getting undefined messages because your build function is outside of the _SignupScreenState class, so just put it inside and those errors will be fixed. And about 4 positional argument(s) expected, but 2 found. Try adding the missing arguments. error, it's probably that your signUp function requires two more arguments, but I don't have source code of it so I can't tell for sure.
Try this:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../models/authentication.dart';
class SignupScreen extends StatefulWidget {
static const routeName = '/signup';
#override
_SignupScreenState createState() => _SignupScreenState();
}
class _SignupScreenState extends State<SignupScreen> {
final GlobalKey<FormState> _formKey = GlobalKey();
TextEditingController _passwordController = new TextEditingController();
Map<String, String> _authData = {
'email': '',
'password': ''
};
void _showErrorDialog(String msg) {
showDialog(
context: context,
builder: (ctx) =>
AlertDialog(
title: Text('An Error Occured'),
content: Text(msg),
actions: <Widget>[
FlatButton(
child: Text('Okay'),
onPressed: () {
Navigator.of(ctx).pop();
},
)
],
)
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Signup'),
actions: <Widget>[
FlatButton(
child: Row(
children: <Widget>[
Text('Login'),
Icon(Icons.person)
],
),
textColor: Colors.white,
onPressed: () {
Navigator.of(context).pushReplacementNamed(LoginScreen.routeName);
},
)
],
),
body: Stack(
children: <Widget>[
Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Colors.limeAccent,
Colors.redAccent,
]
)
),
),
Center(
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
child: Container(
height: 300,
width: 300,
padding: EdgeInsets.all(16),
child: Form(
key: _formKey,
child: SingleChildScrollView(
child: Column(
children: <Widget>[
//email
TextFormField(
decoration: InputDecoration(labelText: 'Email'),
keyboardType: TextInputType.emailAddress,
validator: (value) {
if (value!.isEmpty || !value.contains('#')) {
return 'invalid email';
}
return null;
},
onSaved: (value) {
_authData['email'] = value!;
},
),
//password
TextFormField(
decoration: InputDecoration(labelText: 'Password'),
obscureText: true,
controller: _passwordController,
validator: (value) {
if (value!.isEmpty || value.length <= 5) {
return 'invalid password';
}
return null;
},
onSaved: (value) {
_authData['password'] = value!;
},
),
//Confirm Password
TextFormField(
decoration: InputDecoration(
labelText: 'Confirm Password'),
obscureText: true,
validator: (value) {
if (value!.isEmpty ||
value != _passwordController.text) {
return 'invalid password';
}
return null;
},
onSaved: (value) {
},
),
SizedBox(
height: 30,
),
RaisedButton(
child: Text(
'Submit'
),
onPressed: () {
_submit();
},
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30),
),
color: Colors.blue,
textColor: Colors.white,
)
],
),
),
),
),
),
)
],
),
);
}
Future<void> _submit() async
{
if (!_formKey.currentState!.validate()) {
return;
}
_formKey.currentState!.save();
try {
var key = 'email';
await Provider.of<Authentication>(context, listen: false).signUp(
_authData[key],
_authData['password']
);
Navigator.of(context).pushReplacementNamed(HomeScreen.routeName);
} catch (error) {
var errorMessage = 'Authentication Failed. Please try again later.';
_showErrorDialog(errorMessage);
}
}
}
try {
var key = 'email';
await Provider.of<Authentication>(context, listen: false).signUp(
_authData[key],
_authData['password']
);
Navigator.of(context).pushReplacementNamed(HomeScreen.routeName);
} catch (error) {
var errorMessage = 'Authentication Failed. Please try again later.';
_showErrorDialog(errorMessage);
}
}
}
I am referring to your comment on my previous answer, so no, I can't give you my number, that's not the right way to ask for help, I guess that this site is made for that reason. I reproduced your error and solved it with the explanation written in the comments which you can see in the picture bellow.
So the right way to call your signUp method would be:
Provider.of<Authentication>(context, listen:false).signUp(
authdata['email'] as String,
authdata['password'] as String,
'pass third argument here',
'pass fourth argument here',
);

I'm making a authentication login form then I face this error

I'm making authentication login form and want to connect submitAuthForm Function to the AuthForm. That's why I pass reference in the AuthForm. I am beginner. Please help me to solve this problem (The argument type void Function(String, String, String, bool) can't be assigned to the parameter type void Function(String, String, String, bool)
Thanks.
class AuthScreen extends StatefulWidget {
#override
_AuthScreenState createState() => _AuthScreenState();
}
class _AuthScreenState extends State<AuthScreen> {
void _submitAuthForm(
String email,
String password,
String username,
bool isLogin) {
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Theme.of(context).primaryColor,
body: Authform(_submitAuthForm,)/*( The argument type 'void Function(String, String, String, bool)' can't be assigned to the parameter type 'Void Function(String, String, String, bool)'.*/)
);
}
}
class Authform extends StatefulWidget {
Authform(this.submitFN);
final Void Function(
String email, String password, String username, bool isLogin) submitFN;
#override
_AuthformState createState() => _AuthformState();
}
class _AuthformState extends State<Authform> {
final _formKey = GlobalKey<FormState>();
var _isLogin = true;
var _userEmail;
var _userName;
var _userPassword;
void _trySubmit() {
final isValid = _formKey.currentState!.validate();
FocusScope.of(context).unfocus();
if (isValid) {
_formKey.currentState!.save();
widget.submitFN(_userEmail,_userPassword,_userName,_isLogin);
}
}
#override
Widget build(BuildContext context) {
return Center(
child: Card(
margin: EdgeInsets.all(20),
child: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.all(16),
child: Form(
key: _formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextFormField(
key: ValueKey('email'),
validator: (value) {
if (value!.isEmpty || !value.contains('#')) {
return 'please enter valid email address';
}
return null;
},
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
icon: Icon(
Icons.mail,
color: Colors.orange,
),
labelText: 'Email Addess'),
onSaved: (value) {
_userEmail = value;
},
),
if (!_isLogin)
TextFormField(
key: ValueKey('username'),
validator: (value) {
if (value!.isEmpty || value.length < 4) {
return 'Username is short enter atleast 4 characters ';
}
},
decoration: InputDecoration(
icon: Icon(
Icons.person,
color: Colors.orange,
),
labelText: 'Username'),
onSaved: (value) {
_userName = value;
},
),
TextFormField(
key: ValueKey('password'),
validator: (value) {
if (value!.isEmpty || value.length < 7) {
return 'Password must be atleast 7 characters long';
}
return null;
},
decoration: InputDecoration(
icon: Icon(
Icons.lock,
color: Colors.orange,
),
labelText: 'password',
),
obscureText: true,
onSaved: (value) {
_userPassword = value;
},
),
SizedBox(
height: 12,
),
ElevatedButton(
onPressed: _trySubmit,
child: Text(_isLogin ? 'Login' : 'Signup'),
style: ElevatedButton.styleFrom(onPrimary: Colors.white),
),
TextButton(
onPressed: () {
setState(() {
_isLogin = !_isLogin;
});
},
child: Text(_isLogin
? 'Create new account'
: 'I already have a acoount'))
],
)),
)),
),
);
}
}
When declaring a function or variable you have follow proper declaring method to avoid unusual issues. You have declare your function using Void the V is in capital case there but it must be in small case like void. Juts change this like :
final Void Function(
to
final void Function(
import 'package:flutter/material.dart';
void main(List<String> args) {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(),
home: AuthScreen(),
);
}
}
class AuthScreen extends StatefulWidget {
#override
_AuthScreenState createState() => _AuthScreenState();
}
class _AuthScreenState extends State<AuthScreen> {
void _submitAuthForm(
String email, String password, String username, bool isLogin) {}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Theme.of(context).primaryColor,
body: Authform(
_submitAuthForm,
));
}
}
class Authform extends StatefulWidget {
Authform(this.submitFN);
final void Function(
String email, String password, String username, bool isLogin) submitFN;
#override
_AuthformState createState() => _AuthformState();
}
class _AuthformState extends State<Authform> {
final _formKey = GlobalKey<FormState>();
var _isLogin = true;
var _userEmail;
var _userName;
var _userPassword;
void _trySubmit() {
final isValid = _formKey.currentState!.validate();
FocusScope.of(context).unfocus();
if (isValid) {
_formKey.currentState!.save();
widget.submitFN(_userEmail, _userPassword, _userName, _isLogin);
}
}
#override
Widget build(BuildContext context) {
return Center(
child: Card(
margin: EdgeInsets.all(20),
child: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.all(16),
child: Form(
key: _formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextFormField(
key: ValueKey('email'),
validator: (value) {
if (value!.isEmpty || !value.contains('#')) {
return 'please enter valid email address';
}
return null;
},
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
icon: Icon(
Icons.mail,
color: Colors.orange,
),
labelText: 'Email Addess'),
onSaved: (value) {
_userEmail = value;
},
),
if (!_isLogin)
TextFormField(
key: ValueKey('username'),
validator: (value) {
if (value!.isEmpty || value.length < 4) {
return 'Username is short enter atleast 4 characters ';
}
},
decoration: InputDecoration(
icon: Icon(
Icons.person,
color: Colors.orange,
),
labelText: 'Username'),
onSaved: (value) {
_userName `enter code here`= value;
},
),
TextFormField(
key: ValueKey('password'),
validator: (value) {
if (value!.isEmpty || value.length < 7) {
return 'Password must be atleast 7 characters long';
}
return null;
},
decoration: InputDecoration(
icon: Icon(
Icons.lock,
color: Colors.orange,
),
labelText: 'password',
),
obscureText: true,
onSaved: (value) {
_userPassword = value;
},
),
SizedBox(
height: 12,
),
ElevatedButton(
onPressed: _trySubmit,
child: Text(_isLogin ? 'Login' : 'Signup'),
style: ElevatedButton.styleFrom(onPrimary: Colors.white),
),
TextButton(
onPressed: () {
setState(() {
_isLogin = !_isLogin;
});
},
child: Text(_isLogin
? 'Create new account'
: 'I already have a acoount'))
],
)),
)),
),
);
}
}
account_screen.dart
child: AuthForm(
submitFn: _submitAuthForm,
),

Flutter redirects on textFormField open

whenever i click on the textFormField the keyboard opens and closes almost immediately i think it kinda refreshes the page. i have another page with a form where i dont face this problem.
here is the code for that page, the other form i have in the app is almost identical to this one
import 'package:flutter/material.dart';
import 'package:scoped_model/scoped_model.dart';
import '../scoped_models/products.dart';
class ProductAdd extends StatelessWidget {
final _formData = {
'title': null,
'description': null,
'price': null,
'image': 'assets/food.jpg'
};
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
Widget _titleField() {
return TextFormField(
decoration: InputDecoration(labelText: 'Enter Title'),
keyboardType: TextInputType.text,
validator: (String value) {
if (value.isEmpty) {
return 'Please enter a valid title';
}
},
onSaved: (value) {
print(value);
_formData['title'] = value;
},
);
}
Widget _descriptionField() {
return TextFormField(
decoration: InputDecoration(labelText: 'Enter Description'),
keyboardType: TextInputType.text,
validator: (String value) {
if (value.isEmpty) {
return 'Please enter a valid description';
}
},
onSaved: (value) {
print(value);
_formData['description'] = value;
},
);
}
Widget _priceField() {
return TextFormField(
decoration: InputDecoration(labelText: 'Enter Price'),
keyboardType: TextInputType.number,
validator: (String value) {
if (value.isEmpty) {
return 'Please enter a valid price';
}
},
onSaved: (value) {
print(value);
_formData['price'] = value;
},
);
}
Widget _submitButton(context) {
return RaisedButton(
textColor: Colors.white,
child: Text('LOGIN'),
onPressed: () {
if (!_formKey.currentState.validate()) {
return;
}
_formKey.currentState.save();
Navigator.pushReplacementNamed(context, '/products');
},
);
}
#override
Widget build(BuildContext context) {
return ScopedModelDescendant<ProductsModel>(
builder: (context, child, ProductsModel model) {
return Container(
child: Center(
child: Container(
child: SingleChildScrollView(
child: Container(
padding: EdgeInsets.all(20.0),
child: Form(
key: _formKey,
child: Column(
children: <Widget>[
_titleField(),
_descriptionField(),
_priceField(),
SizedBox(
height: 10.0,
),
_submitButton(context)
],
),
),
),
),
),
),
);
},
);
}
}
i'm using flutter version: 1.0.0
I was not able to reproduce the issue. I re-created your case and the keyboard worked just fine. I although skipped the scoped-model part of your code because I don't know how your setup is. But with minimal code, I couldn't replicate it. See below:
import 'package:flutter/material.dart';
import 'package:scoped_model/scoped_model.dart';
//import '../scoped_models/products.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: ProductAdd(),
);
}
}
class ProductAdd extends StatelessWidget {
final _formData = {
'title': null,
'description': null,
'price': null,
'image': 'assets/food.jpg'
};
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
Widget _titleField() {
return TextFormField(
decoration: InputDecoration(labelText: 'Enter Title'),
keyboardType: TextInputType.text,
validator: (String value) {
if (value.isEmpty) {
return 'Please enter a valid title';
}
},
onSaved: (value) {
print(value);
_formData['title'] = value;
},
);
}
Widget _descriptionField() {
return TextFormField(
decoration: InputDecoration(labelText: 'Enter Description'),
keyboardType: TextInputType.text,
validator: (String value) {
if (value.isEmpty) {
return 'Please enter a valid description';
}
},
onSaved: (value) {
print(value);
_formData['description'] = value;
},
);
}
Widget _priceField() {
return TextFormField(
decoration: InputDecoration(labelText: 'Enter Price'),
keyboardType: TextInputType.number,
validator: (String value) {
if (value.isEmpty) {
return 'Please enter a valid price';
}
},
onSaved: (value) {
print(value);
_formData['price'] = value;
},
);
}
Widget _submitButton(context) {
return RaisedButton(
textColor: Colors.white,
child: Text('LOGIN'),
onPressed: () {
if (!_formKey.currentState.validate()) {
return;
}
_formKey.currentState.save();
Navigator.pushReplacementNamed(context, '/products');
},
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Container(
child: SingleChildScrollView(
child: Container(
padding: EdgeInsets.all(20.0),
child: Form(
key: _formKey,
child: Column(
children: <Widget>[
_titleField(),
_descriptionField(),
_priceField(),
SizedBox(
height: 10.0,
),
_submitButton(context)
],
),
),
),
),
),
),
);
}
}
My Flutter version: 0.11.10
this is my correction, hope it works; u need to add TextEditingController titlecontroller froeach TextFormField,dont use onsaved() ; and on the submitbutton funtion use this :
TextEditingController _pricecontroller;
Widget _priceField() {
return TextFormField(
//addcontroller;
controller : __pricecontroller
decoration: InputDecoration(labelText: 'Enter Price'),
keyboardType: TextInputType.number,
validator: (String value) {
if (value.isEmpty) {
return 'Please enter a valid price';
}
},
onSaved: (value) {
print(value);
_formData['price'] = value;
},
);
}
Widget _submitButton(context) {
return RaisedButton(
textColor: Colors.white,
child: Text('LOGIN'),
onPressed: () {
if (!_formKey.currentState.validate()) {
_formKey.currentState.save();
_formData['title'] = __titlecontroller.text;
_formData['description'] = __desccontroller.text;
_formData['price'] = __pricecontroller.text;
}
Navigator.pushReplacementNamed(context, '/products');
},
);
}