Map keeps returning null values - flutter

I have an issue with creating POST request. No matter what I input, I keep getting null as email and password.
class _LoginPageState extends State<LoginPage> {
late LoginRequestModel requestModel;
#override
void initState() {
super.initState();
requestModel = LoginRequestModel();
}
I have two TextFormFields where I added
onSaved: (input) => requestModel.email = input
Then whenever when input values and I submit on my button it keeps printing {email: null, password: null }
print(requestModel.email); //null
import 'package:flutter/foundation.dart';
class LoginRequestModel {
String? email;
String? password;
LoginRequestModel({ this.email, this.password} );
factory LoginRequestModel.fromJson(Map<String, dynamic> json) {
return LoginRequestModel(
email: json['email'],
password: json['password']
);
}
}
class Auth {
static String baseUrl = "MY_API";
var client = http.Client();
void login(LoginRequestModel model) async {
await client.post(Uri.parse(baseUrl), body: model);
}
}
TextFormField(
cursorColor: Colors.black,
obscureText: false,
onSaved: (input) => requestModel.email = input,
How do I successfully make a POST request?

Simply you can do with the TextEditingController for responsive input and for post network call you need to jsonEncode
class ResponsiveInput extends StatelessWidget {
ResponsiveInput({Key key}) : super(key: key);
TextEditingController emailTextEditingController = TextEditingController();
TextEditingController passwordTextEditingController = TextEditingController();
#override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
padding: EdgeInsets.only(left: 30, right: 30),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextFormField(
controller: emailTextEditingController,
cursorColor: Colors.black,
obscureText: false,
onSaved: (input) {},
),
TextFormField(
controller: passwordTextEditingController,
cursorColor: Colors.black,
obscureText: false,
onSaved: (input) {},
),
TextButton(onPressed: (){
LoginRequestModel login = LoginRequestModel(
email: emailTextEditingController.text,
password: passwordTextEditingController.text,
);
Auth().login(login);
}, child: Text("Login"))
],
),
);
}
}
For complete source code: link
output:

I think that there's some problem while saving your Form Try below code
class _MyHomePageState extends State<MyHomePage> {
LoginRequestModel _requestModel = LoginRequestModel();
GlobalKey<FormState> _globalKey = GlobalKey();
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.green,
body: Form(
key: _globalKey,
child: Column(
children: [
TextFormField(
cursorColor: Colors.black,
obscureText: false,
onSaved: (input) => _requestModel.email = input,
),
TextFormField(
cursorColor: Colors.black,
obscureText: false,
onSaved: (input) => _requestModel.email = input,
),
Divider(),
ElevatedButton(
onPressed: () {
if (_globalKey.currentState!.validate()) {
_globalKey.currentState!.save();
Auth().login(_requestModel);
}
},
child: Text("Submit"))
],
),
),
);
}
}

Related

Flutter - RestAPI - Login

Here I'm going to login using RestAPI.
And the API link they have given me is link1 and they told me to use that to do login.
And also they told me that I can get the list of users with the help of this API link2.
So how do I know that login is successful or not?
I tried below code and whatever I entered and press login it printing Success.
How do I do this in correct way?
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class Login extends StatefulWidget {
const Login({Key? key}) : super(key: key);
#override
State<Login> createState() => _LoginState();
}
class _LoginState extends State<Login> {
late final TextEditingController _email;
late final TextEditingController _password;
final _formKey = GlobalKey<FormState>();
#override
void initState() {
_email = TextEditingController();
_password = TextEditingController();
super.initState();
}
#override
void dispose() {
_email.dispose();
_password.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// Email
Padding(
padding: const EdgeInsets.all(15.0),
child: TextFormField(
controller: _email,
decoration: const InputDecoration(
label: Text('Email'),
),
validator: (value) {
if (value!.isEmpty) {
return 'Email is required';
}
return null;
},
),
),
// Password
Padding(
padding: const EdgeInsets.all(15.0),
child: TextFormField(
controller: _password,
keyboardType: TextInputType.emailAddress,
obscureText: true,
decoration: const InputDecoration(
label: Text('Password'),
),
validator: (value) {
if (value!.isEmpty) {
return 'Password is required';
}
return null;
},
),
),
// Login Button
Padding(
padding: const EdgeInsets.all(15.0),
child: ElevatedButton(
onPressed: () async {
if (_formKey.currentState!.validate()) {
try {
var response = await http.post(
// Uri.parse('https://retoolapi.dev/B13laa/getusers'),
Uri.parse(
'https://retoolapi.dev/B13laa/getusers?user_id=<value1>&password=<value2>',
),
body: ({
'email': _email.text,
'password': _password.text,
}),
);
if (response.statusCode == 200 ||
response.statusCode == 400) {
print('Success');
} else {
print('Failed');
}
} catch (e) {
print(e.toString());
}
}
},
child: const Text('Login'),
),
),
],
),
),
);
}
}
When you enter an invalid user_id and/or password, you get an empty response.
response.statusCode is 200 though.
You have to look at response.body to see the list of users. If it is empty, the login was not successful.

i can't call setState() method in stf Widget

i try to save value in EMAIL variable with onChanged by used setState but the setState function not defined. i can't call it .
MyTextField is statefulWidget. what is problem i don't know .is problem related with Widget class (_buildAllTextFormField)? or what i'm beginner can anyone help me please?
import 'package:ecommernce_application/screens/signup.dart';
import 'package:flutter/material.dart';
import '../widgets/move_to_sign_or_login_screen.dart';
import '../widgets/sign_login_button.dart';
import '../widgets/text_field.dart';
class Login extends StatefulWidget {
const Login({Key? key}) : super(key: key);
#override
State<Login> createState() => _LoginState();
}
final _formKey = GlobalKey<FormState>();
bool obscureText = true;
// for validate Email
String pEmail = 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,}))$';
RegExp regExp = RegExp(pEmail);
void validate(){
final FormState? form = _formKey.currentState;
if(form!.validate())
{ debugPrint('Yes'); }
else { debugPrint('No'); }
}
String EMAIL='';
Widget _buildAllTextFormField(BuildContext context){
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
padding: const EdgeInsets.only(top: 100),
width: double.infinity,
height: 240,
alignment: Alignment.center,
child: const Text('Login',style: TextStyle(fontSize: 40,),),
),
const SizedBox(height: 10,),
Form(
key: _formKey,
autovalidateMode: AutovalidateMode.always,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const SizedBox(height: 10,),
MyTextField(
onChanged:(v){
///////////////cant call setState The function 'setState' isn't defined
//setState((){});
},
controller: email,
validator: (String? value) {
if(value == null || value.trim().isEmpty) {
return 'Please enter your email address';
} // Check if the entered email has the right format
if (!regExp.hasMatch(value)) {
return 'Please enter a valid email address';
} // Return null if the entered email is valid
return null;
},
name: 'Email',),
const SizedBox(height: 10,),
MyTextField(
onChanged: (value){
},
controller: password,
name: 'Password',
validator: (value){
if (value == null || value.trim().isEmpty) {
return 'This field is required';
}
if (value.trim().length < 8) {
return 'Password must be at least 8 characters in length';
} // Return null if the entered password is valid
return null;
}),
const SizedBox(height: 10,),
_buildBottomPart(context),
],
),
),
],
);
}
Widget _buildBottomPart(BuildContext context){
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SignLoginButton(
name: 'Login',
onPressed:() { validate(); } ,
color: Colors.grey,
),
const SizedBox( height: 10, ),
Padding(
padding: const EdgeInsets.only( left:8.0 ),
child:MoveToScreen(
text1:'I Have Noy Account',
text2:'SignUp',
onTap: () {
Navigator.of(context).pushReplacement ( MaterialPageRoute(builder: (context) => const SignUP() ) );
},
),
),
],
);
}
final TextEditingController email = TextEditingController();
final TextEditingController password = TextEditingController();
class _LoginState extends State<Login> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: SingleChildScrollView(
child:TextField(
onChanged: (v){
setState(() {
});
},
),
// _buildAllTextFormField(context),
),
),
);
}
MyTextField
import 'package:flutter/material.dart';
class MyTextField extends StatefulWidget {
final TextEditingController controller;
final String name;
final ValueChanged<String> onChanged;
final FormFieldValidator<String> validator;
const MyTextField({Key? key ,required this.onChanged,required this.controller, required this.name, required this.validator,}) : super(key: key);
#override
State<MyTextField> createState() => _MyTextFieldState();
}
class _MyTextFieldState extends State<MyTextField> {
#override
Widget build(BuildContext context) {
return SizedBox(
width: 400,
height: 50,
child: TextFormField(
controller: widget.controller,
validator: widget.validator,
onChanged: widget.onChanged,
decoration: InputDecoration(
labelText: widget.name,
border: const OutlineInputBorder(),
),
),
);
}
}
PasswordTextField
import 'package:flutter/material.dart';
class PasswordTextField extends StatefulWidget {
final TextEditingController controller;
final String name;
final FormFieldValidator<String> validator;
//final ValueChanged<String> onChange;
const PasswordTextField({Key? key, required this.controller, required this.name, required this.validator}) : super(key: key);
#override
State<PasswordTextField> createState() => _PasswordTextFieldState();
}
class _PasswordTextFieldState extends State<PasswordTextField> {
bool _obscureText = true ;
#override
Widget build(BuildContext context) {
return SizedBox(
width: 400,
height: 50,
child: TextFormField(
obscureText: _obscureText,
validator: widget.validator,
//onChanged: widget.onChange,
controller: widget.controller,
decoration: InputDecoration(
suffixIcon: GestureDetector(
onTap: (){
setState(() {
_obscureText =!_obscureText;
});
FocusScope.of(context).unfocus();
},
child: Icon( _obscureText == true ? Icons.visibility : Icons.visibility_off,color: Colors.black,),),
labelText: widget.name,
border: const OutlineInputBorder(),
),
),
);
}
}
You can do it in this way:
Widget _buildAllTextFormField(BuildContext context, Function() changeCallback){...}
then replace:
_buildAllTextFormField(context)
with
_buildAllTextFormField(context, () => setState((){}))
and then replace:
onChanged:(v){
///////////////cant call setState The function 'setState' isn't defined
//setState((){});
},
with:
onChanged:(v){
changeCallback.call();
},

My Bloc Consumer doesn't listen to states

when i call the method fetchData from ColorsCubit the BlocConsumer doesn't listen to states i call fetch data method in initial state and it must liseten to loading state before fetching method and loaded state after fetching method but it doesn't listen to states , in listener i print the state of each one but it doesn't print it i don't know the reason
class ColorsCubit extends Cubit<ColorsStates>{
ColorsCubit() : super(InitialState());
static ColorsCubit get(context)=>BlocProvider.of(context);
List items=[];
String color="";
String errorMessage="";
String errorValue="";
String redColor="";
String value="mohamed";
List<dynamic> colors=[];
Future<void> fetchData()async{
emit(LoadingState());
final String response = await rootBundle.loadString('assets/data.json');
final data = await json.decode(response);
emit(LoadedState());
items=data["groupOfColors"]["asyncValidationColors"];
color=items[0]["color"];
errorMessage=items[0]["errorMessage"];
errorValue=items[0]["error"];
colors=data["groupOfColors"]["autoSuggestionsColors"];
redColor=data["red"];
}
List<dynamic> getSuggestions(String query)=>
colors.where((element) {
final elementLower=element.toLowerCase();
final queryLower=query.toLowerCase();
return elementLower.contains(queryLower);
}).toList();
bool checkFirstColor(String query){
return query=="Bluee"?true:false;
}
Future<void> sendDataToApi(String firstColor,String secondColor,String thirdColor,String fourthColor)async{
await ApiProvider().saveDataToApi(firstColor, secondColor, thirdColor, fourthColor);
}
}
//this is the states class
abstract class ColorsStates{}
class InitialState extends ColorsStates{}
class LoadingState extends ColorsStates{}
class LoadedState extends ColorsStates{}
//this is the BlocConsumer
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
#override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
ColorsCubit cubit = ColorsCubit();
TextEditingController firstColorController = TextEditingController();
TextEditingController secondColorController = TextEditingController();
TextEditingController thirdColorController = TextEditingController();
late TextEditingController fourthColorController =
TextEditingController(text: "redColor");
bool _enableButton = false;
bool _secondVisible = true;
final key = GlobalKey<FormState>();
void _saveData() {
cubit.sendDataToApi(firstColorController.text, secondColorController.text,
thirdColorController.text, fourthColorController.text);
}
#override
void initState() {
cubit.fetchData();
super.initState();
}
#override
void dispose() {
firstColorController.dispose();
secondColorController.dispose();
thirdColorController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => ColorsCubit(),
child: BlocConsumer<ColorsCubit, ColorsStates>(
listener: (context, state) {
if(state is InitialState) print("in initial state");
if (state is LoadingState) print("in loading state");
if (state is LoadedState) print("in loaded state");
},
builder: (context, state) {
if (state is LoadedState) {
return _buildLoadingIndicator();
} else {
return Scaffold(
appBar: AppBar(
title: const Text("Colors"),
actions: [
IconButton(onPressed: ()=>Navigator.of(context).push(MaterialPageRoute(builder: (context)=>const SecondScreen())), icon:const Icon(Icons.arrow_forward))
],
),
body: Center(
child: Form(
onChanged: () => setState(() {
_enableButton = key.currentState!.validate();
}),
key: key,
child: Padding(
padding: const EdgeInsets.all(15),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextFormField(
keyboardType: TextInputType.text,
controller: firstColorController,
onChanged: (value) {
setState(() {
_secondVisible =
!firstColorController.text.startsWith('a');
});
},
decoration: const InputDecoration(
border: OutlineInputBorder(),
hintText: "first color"),
validator: (query) {
if (query!.isEmpty) {
return "color can't be empty";
} else if (query.trim().length < 5 ||
query.trim().length > 9) {
return "colors can't be less than 5 chars or greater than 9 chars";
} else if (cubit.checkFirstColor(query.trim())) {
return cubit.errorMessage;
}
},
),
const SizedBox(
height: 15,
),
Visibility(
visible: _secondVisible,
child: TextFormField(
keyboardType: TextInputType.text,
controller: secondColorController,
decoration: const InputDecoration(
border: OutlineInputBorder(),
hintText: "second color"),
validator: (value) {
if (value!.isEmpty) {
return "value can't be empty";
}
return null;
},
),
),
const SizedBox(
height: 15,
),
TypeAheadFormField(
textFieldConfiguration: TextFieldConfiguration(
controller: thirdColorController,
decoration: const InputDecoration(
hintText: "third color",
border: OutlineInputBorder())),
onSuggestionSelected: (suggestion) {
thirdColorController.text =
suggestion.toString();
},
itemBuilder: (context, suggestion) {
return ListTile(
title: Text(suggestion.toString()),
);
},
noItemsFoundBuilder: (context) => const SizedBox(
height: 100,
child: Center(
child: Text(
"no colors",
style: TextStyle(
fontWeight: FontWeight.bold),
)),
),
validator: (query) {
if (query!.isEmpty) {
return "second color can't be empty";
}
return null;
},
suggestionsCallback: cubit.getSuggestions),
const SizedBox(
height: 15,
),
TextFormField(
keyboardType: TextInputType.text,
decoration: const InputDecoration(
border: OutlineInputBorder(),
),
enabled: false,
initialValue: cubit.redColor,
),
TextButton(
onPressed: _enableButton ? _saveData : null,
child: const Text("Save Data"))
],
),
),
),
),
);
}
},
)
);
}
}
Widget _buildLoadingIndicator() {
return const Center(
child: CircularProgressIndicator(),
);
}
enter code here

How to pass TextEditingController's reference variable Form one class to another

I have one page called registerUser.dart example code is given billow:
import 'package:http/http.dart' as http;
import 'package:login/URL/urls.dart';
class UserRegister extends StatefulWidget {
const UserRegister({Key key}) : super(key: key);
#override
_UserRegisterState createState() => _UserRegisterState();
}
class _UserRegisterState extends State<UserRegister> {
GlobalKey<FormState> key = GlobalKey<FormState>();
TextEditingController firstName = TextEditingController();
TextEditingController LastName = TextEditingController();
TextEditingController email = TextEditingController();
// var listOFUrl =listOFallUrl(firstName,this.LastName,this.email);
final surj =new listOFallUrl.myUrlConstructor(firstName.text);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Lab Work"),
),
body: SingleChildScrollView(
child: Form(
key: key,
child: Column(
children: <Widget>[
TextFormField(
controller: firstName,
decoration: InputDecoration(labelText: 'Item Name'),
validator: (value) =>
value.isEmpty ? 'this field cannot be empty' : null,
),
TextFormField(
decoration: InputDecoration(labelText: 'Item Price'),
validator: (value) =>
value.isEmpty ? 'this field cannot be empty' : null,
controller: LastName,
),
TextFormField(
controller: email,
decoration: InputDecoration(labelText: 'Item Description'),
validator: (value) =>
value.isEmpty ? 'this field cannot be empty' : null,
),
ElevatedButton(
onPressed: () {
if (key.currentState.validate()) {
// putProduct();
print("record inserted");
}
},
child: Text('Save'),
)
],
),
),
));
}
}
And want use above firstName,lastName and email TextEditingController into this page called urls.dart. How can do that ? I tried to pass textEditorController using refrence Variable of listOFallUrl class but that did't work out.
import 'package:http/http.dart' as http;
class listOFallUrl{
listOFallUrl(TextEditingController firtname){}
listOFallUrl.myUrlConstructor(){
print("this is example");
}
void URL(TextEditingController firtname){
}
} ```
need to declaration of List in your code, Try below code:
class UserRegister extends StatefulWidget {
//const UserRegister({Key key}) : super(key: key);
#override
_UserRegisterState createState() => _UserRegisterState();
}
class _UserRegisterState extends State<UserRegister> {
GlobalKey<FormState> key = GlobalKey<FormState>();
TextEditingController firstName = TextEditingController();
TextEditingController LastName = TextEditingController();
TextEditingController email = TextEditingController();
putProduct(List<TextEditingController> surj){
listOFallUrl(surj);
}
#override
Widget build(BuildContext context) {
List<TextEditingController> surj;
return Scaffold(
appBar: AppBar(
title: Text("Lab Work"),
),
body: SingleChildScrollView(
child: Form(
key: key,
child: Column(
children: <Widget>[
TextFormField(
controller: firstName,
decoration: InputDecoration(labelText: 'Item Name'),
validator: (String? value) {
if (value != null && value.isEmpty) {
return "this field cannot be empty";
}
return null;
}),
TextFormField(
controller: LastName,
decoration: InputDecoration(labelText: 'Item Price'),
validator: (String? value) {
if (value != null && value.isEmpty) {
return "this field cannot be empty";
}
return null;
}),
TextFormField(
controller: email,
decoration: InputDecoration(labelText: 'Item Description'),
validator: (String? value) {
if (value != null && value.isEmpty) {
return "this field cannot be empty";
}
return null;
}),
ElevatedButton(
onPressed: () {
if (key.currentState!.validate()) {
surj=[firstName,LastName,email];
putProduct(surj);
print("record inserted");
}
},
child: Text('Save'),
)
],
),
),
));
}
}
class listOFallUrl {
List<TextEditingController> l;
listOFallUrl(this.l);
void URL(List<TextEditingController> l) {
print(l[0]);
print(l[1]);
print(l[2]);
}
}

Flutter - How implement one E-Mail TextFormField widget for using in multiple screens?

I'm developing a app with a register, login and reset password screen. In all this screens the user must enter his e-mail address. Now i will not implement the e-mail address textfield for every single screen. So i will implement a email textfield widget for every screen like the code below.
import 'package:flutter/material.dart';
import 'package:email_validator/email_validator.dart';
class EMailTextFormField extends StatefulWidget {
#override
_EMailTextFormFieldState createState() => _EMailTextFormFieldState();
}
class _EMailTextFormFieldState extends State<EMailTextFormField> {
final _email = TextEditingController();
#override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 3.0),
child: TextFormField(
decoration: InputDecoration(
icon: Icon(Icons.email, size: IconTheme.of(context).size, color: IconTheme.of(context).color),
labelText: 'E-Mail...',
counterText: '',
),
keyboardType: TextInputType.emailAddress,
controller: _email,
validator: _validateEmail,
maxLength: 70,
),
);
}
String _validateEmail(String email) {
// validate E-Mail function...
}
}
My problem is now that i can't use the TextEditingController (_email) outside this widget in the different screens (register, login and reset password) like this as a example:
final FirebaseUser user = (await _auth.createUserWithEmailAndPassword(
email: _email.text.toString(), password: _password.text.toString())).user;
The error is "Undefined name _email" because the _email TextEditingController is in the EMailTextFormField widget, but how can i give the value of the _email field from EMailTextFormField widget to the other screens (register, login and reset password)?
Can anyone help me i found so far no solution.
You can do this using onSaved callback.
EMailTextFormField:
class EMailTextFormField extends StatefulWidget {
final void Function(String email) onSaved;
const EMailTextFormField({Key key, this.onSaved}) : super(key: key);
#override
EMailTextFormFieldState createState() => EMailTextFormFieldState();
}
class EMailTextFormFieldState extends State<EMailTextFormField> {
final _email = TextEditingController();
#override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 3.0),
child: TextFormField(
decoration: InputDecoration(
icon: Icon(Icons.email, size: IconTheme.of(context).size, color: IconTheme.of(context).color),
labelText: 'E-Mail...',
counterText: '',
),
keyboardType: TextInputType.emailAddress,
controller: _email,
validator: _validateEmail,
maxLength: 70,
onSaved: widget.onSaved, //callback
),
);
}
String _validateEmail(String email) {
// validate E-Mail function...
}
}
Page where you will use EMailTextFormField:
class EmailPage extends StatefulWidget {
EmailPage({Key key}) : super(key: key);
#override
_EmailPageState createState() => _EmailPageState();
}
class _EmailPageState extends State<EmailPage> {
String _email;
final _formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Email Page'),
),
body: Form(
key: _formKey,
child: Column(
children: <Widget>[
EMailTextFormField(
onSaved: (String email) => _email = email,
),
RaisedButton(
child: Text('Go'),
onPressed: (){
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
print(_email);
}
},
)
],
),
),
);
}
}