I have tried making an authentication screen for my app I am unable to signup as it's showing the password does not match as I have set up a text form validation. The data is not also showing up in the firebase authentication so I think there could be a problem with the API request. I have not put.json after the URI.parse for auth as i saw somewhere we don't(tried after putting it but it did not work).
Authentication screen:
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../Providers/auth.dart';
enum AuthMode { Signup, Login }
class AuthScreen extends StatelessWidget {
static const routeName = '/auth';
@override
Widget build(BuildContext context) {
final deviceSize = MediaQuery.of(context).size;
// final transformConfig = Matrix4.rotationZ(-8 * pi / 180);
// transformConfig.translate(-10.0);
return Scaffold(
// resizeToAvoidBottomInset: false,
body: Stack(
children: <Widget>[
Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Color.fromRGBO(215, 117, 255, 1).withOpacity(0.5),
Color.fromRGBO(255, 188, 117, 1).withOpacity(0.9),
],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
stops: [0, 1],
),
),
),
SingleChildScrollView(
child: Container(
height: deviceSize.height,
width: deviceSize.width,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Flexible(
child: Container(
margin: EdgeInsets.only(bottom: 20.0),
padding:
EdgeInsets.symmetric(vertical: 8.0, horizontal: 94.0),
transform: Matrix4.rotationZ(
-8 * pi / 180) //allows to rotate the container
..translate(
-10.0), //adds offset to matrix; .. operater changes the product from inside
// ..translate(-10.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.deepOrange.shade900,
boxShadow: [
BoxShadow(
blurRadius: 8,
color: Colors.black26,
offset: Offset(0, 2),
)
],
),
child: Text(
'MyShop',
style: TextStyle(
color: Colors
.black, //Theme.of(context).accentTextTheme.title.color,
fontSize: 50,
fontFamily: 'Anton',
fontWeight: FontWeight.normal,
),
),
),
),
Flexible(
flex: deviceSize.width > 600 ? 2 : 1,
child: AuthCard(),
),
],
),
),
),
],
),
);
}
}
class AuthCard extends StatefulWidget {
const AuthCard({
Key? key,
}) : super(key: key);
@override
_AuthCardState createState() => _AuthCardState();
}
class _AuthCardState extends State<AuthCard> {
final GlobalKey<FormState> _formKey = GlobalKey();
AuthMode _authMode = AuthMode.Login;
Map<String, String> _authData = {
'email': '',
'password': '',
};
var _isLoading = false;
final _passwordController = TextEditingController();
Future<void> _submit() async {
if (!_formKey.currentState!.validate()) {
// Invalid!
return;
}
_formKey.currentState!.save();
setState(() {
_isLoading = true;
});
if (_authMode == AuthMode.Login) {
// Log user in
} else {
// Sign user up
await Provider.of<Auth>(context, listen: false).signup(
//as signup returns future we have to aysnc it, we do await to show loading spinner
_authData['email'].toString(),
_authData['password']
.toString()); //authdata is the value we are saviing this as
}
setState(() {
_isLoading = false;
});
}
void _switchAuthMode() {
if (_authMode == AuthMode.Login) {
setState(() {
_authMode = AuthMode.Signup;
});
} else {
setState(() {
_authMode = AuthMode.Login;
});
}
}
@override
Widget build(BuildContext context) {
final deviceSize = MediaQuery.of(context).size;
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
elevation: 8.0,
child: Container(
height: _authMode == AuthMode.Signup ? 320 : 260,
constraints:
BoxConstraints(minHeight: _authMode == AuthMode.Signup ? 320 : 260),
width: deviceSize.width * 0.75,
padding: EdgeInsets.all(16.0),
child: Form(
key: _formKey,
child: SingleChildScrollView(
child: Column(
children: <Widget>[
TextFormField(
decoration: InputDecoration(labelText: 'E-Mail'),
keyboardType: TextInputType.emailAddress,
validator: (value) {
if (value!.isEmpty || !value.contains('@')) {
return 'Invalid email!';
}
return null;
},
onSaved: (value) {
_authData['email'] = value.toString();
},
),
TextFormField(
decoration: InputDecoration(labelText: 'Password'),
obscureText:
true, //which makes sure that the inpur isnt shown to the user
validator: (value) {
if (value!.isEmpty || value.length < 5) {
return 'Password is too short!';
}
},
onSaved: (value) {
_authData['password'] = value.toString();
},
),
if (_authMode == AuthMode.Signup)
TextFormField(
enabled: _authMode == AuthMode.Signup,
decoration: InputDecoration(labelText: 'Confirm Password'),
obscureText: true,
validator: _authMode == AuthMode.Signup
? (value) {
if (value != _passwordController.text) {
return 'Passwords do not match!';
}
}
: null,
),
SizedBox(
height: 20,
),
if (_isLoading)
CircularProgressIndicator()
else
RaisedButton(
child:
Text(_authMode == AuthMode.Login ? 'LOGIN' : 'SIGN UP'),
onPressed: _submit,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30),
),
padding:
EdgeInsets.symmetric(horizontal: 30.0, vertical: 8.0),
color: Theme.of(context).primaryColor,
textColor: Theme.of(context).primaryTextTheme.button!.color,
),
FlatButton(
child: Text(
'${_authMode == AuthMode.Login ? 'SIGNUP' : 'LOGIN'} INSTEAD'),
onPressed: _switchAuthMode,
padding: EdgeInsets.symmetric(horizontal: 30.0, vertical: 4),
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
textColor: Theme.of(context).primaryColor,
),
],
),
),
),
),
);
}
}
Auth.dart:
class Auth with ChangeNotifier {
late String _token;
late DateTime _expiryDate;
late String _userId;
Future<void> signup(String username, String password) async {
var url = Uri.parse(
'https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=[Auth Key]');
final response = await http.post(url,
body: jsonEncode({
'username': username,
'password': password,
'returnSecureToken':
true
}));
print(json.decode(response.body));
}
}
Also, getting no error message or any messages in debug console. Thanks in advance for helping
CodePudding user response:
You need have separate TextEditingController for each of your TextFormField widgets, if you'd like to read the values with controller.value.
You also have to assign the appropriate controller to each TextFormField like this:
TextFormField(
controller: _controllerForThisField,
...
),
Also, do not forget to properly dispose all controllers when the widget is disposed, call controller.dispose() for example in an overridden dispose() method.
