I have a basic email contact form that I got from online and I'm trying to send a sample email but some reason I can not enter any text in my input filed. Any suggestion or idea what it might be?
I can enter a text when ever I delete my _formKey but I can not send the email successfully anymore.
Any suggestion or help will be really appreciated.
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:email_validator/email_validator.dart';
import 'package:http/http.dart' as http;
class EmailForm extends StatelessWidget {
EmailForm({Key? key}) : super(key: key);
final _formKey = GlobalKey<FormState>();
final nameController = TextEditingController();
final emailController = TextEditingController();
final messageController = TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xfff5f5fd),
body: Center(
child: Container(
height: 450,
width: 400,
margin: const EdgeInsets.symmetric(
horizontal: 40,
vertical: 20,
),
padding: const EdgeInsets.symmetric(
horizontal: 40,
vertical: 20,
),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
boxShadow: [
BoxShadow(
offset: const Offset(0, 5),
blurRadius: 10,
spreadRadius: 1,
color: Colors.grey[300]!)
]),
child: Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
const Text('Contact Us',
style:
TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
TextFormField(
controller: nameController,
decoration: const InputDecoration(hintText: 'Name'),
validator: (value) {
if (value == null || value.isEmpty) {
return '*Required';
}
return null;
},
),
TextFormField(
controller: emailController,
decoration: const InputDecoration(hintText: 'Email'),
validator: (email) {
if (email == null || email.isEmpty) {
return 'Required*';
} else if (!EmailValidator.validate(email)) {
return 'Please enter a valid Email';
}
return null;
},
),
TextFormField(
controller: messageController,
decoration: const InputDecoration(hintText: 'Message'),
maxLines: 5,
validator: (value) {
if (value == null || value.isEmpty) {
return '*Required';
}
return null;
},
),
SizedBox(
height: 45,
width: 110,
child: TextButton(
style: TextButton.styleFrom(
primary: Colors.white,
backgroundColor: const Color(0xff151534),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(40))),
onPressed: () async {
if (_formKey.currentState!.validate()) {
final response = await sendEmail(
nameController.value.text,
emailController.value.text,
messageController.value.text);
ScaffoldMessenger.of(context).showSnackBar(
response == 200
? const SnackBar(
content: Text('Message Sent!'),
backgroundColor: Colors.green)
: const SnackBar(
content: Text('Failed to send message!'),
backgroundColor: Colors.red),
);
nameController.clear();
emailController.clear();
messageController.clear();
}
},
child: const Text('Send', style: TextStyle(fontSize: 16)),
),
),
],
),
),
),
),
);
}
}
Future sendEmail(String name, String email, String message) async {
final url = Uri.parse('https://api.emailjs.com/api/v1.0/email/send');
final response = await http.post(url,
headers: {'Content-Type': 'application/json'},
body: json.encode({
'service_id': '',
'template_id': '',
'user_id': '',
'template_params': {
'from_name': name,
'from_email': email,
'message': message
}
}));
return response.statusCode;
}
CodePudding user response:
When you're using a Form Widget, you don't necessarily need to use controllers you can used the onchange function in your TextFormField Widget.
Instead of defining TextEditingControllers like this:
final nameController = TextEditingController();
final emailController = TextEditingController();
Do this instead:
var name = '';
var email = '';
Instead of
TextFormField(
controller: nameController,
decoration: const InputDecoration(hintText: 'Name'),
validator: (value) {
if (value == null || value.isEmpty) {
return '*Required';
}
return null;
},
),
Do this:
TextFormField(
decoration: const InputDecoration(hintText: 'Name'),
validator: (value) {
if (value == '') {
return '*Required';
}
return null;
},
onChanged: (value) {
name = value; //If it gives some null check error just add an exclamation like this - name = value!;
}
),
Now you just have to pass these variables in your request just like you use any normal variables. Instead of using nameController.text, just name (variable created in the beginning) is enough. This should make the form work perfectly.
If you are not getting 200 status then the problem could also be the difference between the data you're sending and the data that is expected to receive on the server.
To figure out the root cause, I would recommend you to add Print Statements everywhere to see which functions are running properly and which are not.
Printing the error statements coming from the server might help in understanding the root problem. So try this before returning statusCode
print(response.body); //Add this line for the output from the server
return response.statusCode;
And let me know what reply you get in the console.
CodePudding user response:
Future sendEmail(String name, String email, String message) async {
final url = Uri.parse('https://api.emailjs.com/api/v1.0/email/send');
const serviceId = 'Enter your service Id';
const templateId = 'Enter your template Id';
const userId = 'Enter your User Id';
final response = await http.post(url,
headers: {'Content-Type': 'application/json'},//This line makes sure it works for all platforms.
body: json.encode({
'service_id': serviceId,
'template_id': templateId,
'user_id': userId,
'template_params': {
'from_name': name,
'from_email': email,
'message': message
}
})
);
print (response.body);
return response.statusCode;
}
You will get Service Id, template Id and User Id from the account that you have created on MailJS.