I made some TextFormField, and I want to save the data in int when I press the FlatButton. When I press FlatButton, I want him to check whether the sum of TextFormField expenses and savings is not greater than TextFormField income. if the sum of the TextTormField expenses and savings is greater, I want to display errortext under the textformfield savings "your expenses and savings are greater than your income"
class BigNotePage extends StatefulWidget {
#override
_BigNotePageState createState() => _BigNotePageState();
}
class _BigNotePageState extends State<BigNotePage> {
final _formKey = GlobalKey<FormState>();
String _income;
String _expenses;
String _savings;
#override
Widget build(BuildContext context) {
return Container(
padding: kPading,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TitlePage('Big Note'),
Expanded(
child: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.center,
children: [
TxtField(
label: 'Income',
function: (value) => _income = value,
),
TxtField(
label: 'Expenses',
function: (value) => _expenses = value,
),
TxtField(
label: 'Savings',
function: (value) => _savings = value,
),
FlatButton(
onPressed: () {
int.parse(_income) >=
int.parse(_expenses) + int.parse(_savings)
? _formKey.currentState.save()
: print('null');
},
child: Text(
'WRITE THAT',
style: TextStyle(letterSpacing: 1.25),
),
color: Colors.yellow,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30.0),
),
),
],
),
),
),
Container(
width: 250.0,
child: Text(
'*if you get another income for this mounth, input the income again.',
style: TextStyle(fontSize: 12.0),
),
),
],
),
);
}
}
class TxtField extends StatelessWidget {
TxtField({this.label, this.function});
final String label;
final Function function;
#override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.symmetric(vertical: 8.0),
child: TextFormField(
onSaved: function,
keyboardType: TextInputType.numberWithOptions(decimal: true),
decoration: InputDecoration(
labelText: label,
prefix: Container(
padding: EdgeInsets.all(8.0),
child: Text(
'IDR',
style:
TextStyle(color: Colors.black, fontWeight: FontWeight.bold),
),
),
),
),
);
}
}
Replace String values to the controller values
final _incomeController = TextEditingController();
final _expenseController = TextEditingController();
final _savingController = TextEditingController();
Also, add
bool _validate = false;
Convert String value to int of your TextField:
TextField(
controller: _incomeController,
label: 'Income',
decoration: InputDecoration(
errorText: _validate ? 'Your message' : null,
),
),
TextField(
controller: _expenseController ,
label: 'Expenses',
decoration: InputDecoration(
errorText: _validate ? 'Your message' : null,
),
),
TextField(
controller: _savingController,
label: 'Savings',
decoration: InputDecoration(
errorText: _validate ? 'Your message' : null,
),
),
Now FlatButton Logic:
onPressed: () {
String _income = _incomeController.text;
String _expenses = _expenseController.text;
String _savings = _savingController.text;
int.parse(_income) >=
int.parse(_expenses) + int.parse(_savings)
? _formKey.currentState.save()
: print('null');
},
Rest apply your logic wherever you want.
Related
import 'package:flutter/material.dart';
import 'package:sumanthk07/utilities/routes.dart';
class LoginPage extends StatefulWidget {
const LoginPage({Key? key}) : super(key: key);
#override
State<LoginPage> createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
final _formkey = GlobalKey<FormState>();
// ignore: avoid_types_as_parameter_names, non_constant_identifier_names
moveToHome(BuildContext) async{
Navigator.pushNamed(context, MyRoutes.homeRoute);
}
#override
Widget build(BuildContext context) {
return Material(
color: Colors.white,
child: SingleChildScrollView(
child: Form(
key: _formkey,
child: Column(
children: [
Image.asset("assets/images/login.png", fit: BoxFit.cover),
const SizedBox(
height: 20.0,
),
const Text(
'Welcome',
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
),
const SizedBox(
height: 20.0,
),
Padding(
padding: const EdgeInsets.symmetric(
vertical: 16.0, horizontal: 32.0),
child: Column(
children: [
TextFormField(
decoration: const InputDecoration(
hintText: "Enter User name", labelText: "Username "),
initialValue: "",
validator: (String? value) {
if (value !=null && value.isEmpty ) {
return "User name cannot be empty";
}
return null;
},
onChanged: (value) {
setState(() {});
},
),
TextFormField(
obscureText: true,
decoration: const InputDecoration(
hintText: "Enter password", labelText: "Password "),
initialValue: "",
validator: (String? value) {
if (value !=null && value.isEmpty ) {
return "Password name cannot be empty";
}
return null;
},
),
const SizedBox(
height: 20.0,
),
InkWell(
onTap: () => moveToHome(context),
child: AnimatedContainer(
duration: const Duration(seconds: 1),
height: 40,
width: 80,
alignment: Alignment.center,
child: const Text("Login",
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 18,
)),
decoration: BoxDecoration(
color: Colors.red,
// ignore: unnecessary_const
borderRadius: BorderRadius.circular(20)),
),
)
// ElevatedButton(
// child: const Text("Login"),
// style: TextButton.styleFrom(),
// onPressed: () {
// // ignore: unused_local_variable
// var myRoutes = MyRoutes;
// Navigator.pushNamed(context, MyRoutes.homeRoute);
// },
// )
],
),
)
],
),
),
),
);
}
BorderRadius newMethod() => BorderRadius.circular(20);
}
Hi All, I'm a beginner to flutter and I'm trying to add validator to widget but I'm not getting the validation when I run the application.
I searched and tried the ways to do it but I didn't get the desired outcome.
Can you guys look into my code and suggest the right way.
no errors found but validation is not working.
First assign TextEditingController to your both fields.
final TextEditingController _controllerUserName = TextEditingController();
final TextEditingController _controllerPassword = TextEditingController();
And also assign autovalidateMode to your text field so you can validate at user input like this. It's not necessary it's optional but you can add it to validate your field on input field changes. Although you can validate your form at submission time.
TextFormField(
decoration: const InputDecoration(
hintText: "Enter User name", labelText: "Username "),
initialValue: "",
validator: (String? value) {
if (value !=null && value.isEmpty ) {
return "User name cannot be empty";
}
return null;
},
onChanged: (value) {
setState(() {});
},
autovalidate : AutovalidateMode.onUserInteraction,
controller:_controllerUserName
),
And also you have not validate your form at submission time. try this
moveToHome(BuildContext) async{
if (_formkey.currentState.validate()) {
Navigator.pushNamed(context, MyRoutes.homeRoute);
}
}
I have created a page where user can input their exam result which are subject and grade.
On the page, user need to click the add subject button to add another subject depending on how many subject they have. User also can remove subject by clicking the remove subject button.
The problem is only TextFormField value submitted. How to get the data for DropDownFormField if the form created dynamically?
I have tried the read the data using the onChanged function of the drop down and yes the data was stored to the variable gradeController but it returns null when I submit the data.
This is the model
class SubjectGrade {
final String? name;
final String? grade;
SubjectGrade(this.name, this.grade);
#override
String toString() {
return 'SPM: name = $name, grade = $grade';
}
}
This is the form
import 'package:flutter/material.dart';
import 'package:testing_app/models/education_model.dart';
class EducationBackgroundForm extends StatefulWidget {
const EducationBackgroundForm({Key? key}) : super(key: key);
#override
_EducationBackgroundFormState createState() =>
_EducationBackgroundFormState();
}
class _EducationBackgroundFormState extends State<EducationBackgroundForm> {
final nameTECs = <TextEditingController>[];
final gradeTECs = <String?>[];
final forms = <Form>[];
Form createForm() {
TextEditingController nameController = TextEditingController();
String? gradeController;
nameTECs.add(nameController);
gradeTECs.add(gradeController);
final grades = ['A+', 'A', 'A-', 'B+', 'B', 'C+', 'C', 'D', 'E', 'G'];
DropdownMenuItem<String> buildMenuItem(String item) => DropdownMenuItem(
value: item,
child: Text(item),
);
return Form(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Row(
children: <Widget>[
Expanded(
flex: 2,
child: Column(
children: <Widget>[
TextFormField(
controller: nameController,
decoration: InputDecoration(
hintText: 'Subject Name',
labelText: 'Subject ${forms.length + 1}',
border: const OutlineInputBorder(),
contentPadding:
const EdgeInsets.only(left: 8, right: 8),
),
keyboardType: TextInputType.text,
textInputAction: TextInputAction.done,
),
],
),
),
const SizedBox(width: 5),
Expanded(
flex: 1,
child: Column(
children: <Widget>[
DropdownButtonHideUnderline(
child: DropdownButtonFormField(
value: gradeController,
isExpanded: true,
iconSize: 36,
icon: const Icon(Icons.arrow_drop_down,
color: Colors.black),
items: grades.map(buildMenuItem).toList(),
onChanged: (String? value) {
setState(() {
gradeController = value;
});
},
hint: const Text("Grade"),
decoration: const InputDecoration(
border: OutlineInputBorder(),
contentPadding: EdgeInsets.only(left: 8),
),
),
)
],
)),
],
),
const SizedBox(height: 10)
],
),
);
}
#override
void initState() {
super.initState();
forms.add(createForm());
}
saveSPMResultToFirebase() {
List<SubjectGrade> entries = [];
for (int i = 0; i < forms.length; i++) {
final name = nameTECs[i].text;
final grade = gradeTECs[i].toString();
entries.add(SubjectGrade(name, grade));
}
debugPrint(entries.toString());
//Navigator.pop(context, entries);
}
#override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
const Text("SPM Result", style: TextStyle(fontSize: 18)),
const SizedBox(height: 20),
Expanded(
child: ListView.builder(
itemCount: forms.length,
itemBuilder: (BuildContext context, int index) {
return forms[index];
},
),
),
const SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
child: SizedBox(
width: double.infinity,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.all(14),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8))),
onPressed: () => setState(() {
forms.add(createForm());
}),
child: const Text(
'Add Subject',
style: TextStyle(
fontSize: 16,
),
),
),
),
),
const SizedBox(width: 5),
Expanded(
child: SizedBox(
width: double.infinity,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.all(14),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8))),
onPressed: () => setState(() {
if (forms.length > 1) {
forms.removeAt(forms.length - 1);
}
}),
child: const Text(
'Remove Subject',
style: TextStyle(
fontSize: 16,
),
),
),
),
),
],
),
const SizedBox(height: 10),
SizedBox(
width: double.infinity,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.all(14),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8))),
onPressed: () {
saveSPMResultToFirebase();
},
child: const Text(
'Update',
style: TextStyle(
fontSize: 16,
),
),
),
),
],
);
}
}
When I submit the form, the debug output I get from the submit function for grade is null.
Output:
[SPM: name = English, grade = null]
You should add value of DropDownButton in onChanged method not at top of create form.
change your code to this:
First Delete gradeTECs.add(gradeController); line from top of createForm().
Form createForm() {
TextEditingController nameController = TextEditingController();
String? gradeController;
nameTECs.add(nameController);
// gradeTECs.add(gradeController); <==== DELETE THIS LINE.
Add gradeTECs.add(gradeontroller); in onChanged method of DropdownButtonFormField
DropdownButtonHideUnderline(
child: DropdownButtonFormField(
value: gradeController,
isExpanded: true,
iconSize: 36,
icon: const Icon(Icons.arrow_drop_down,
color: Colors.black),
items: grades.map(buildMenuItem).toList(),
onChanged: (String? value) {
setState(() {
gradeController = value;
gradeTECs.add(gradeController); <=== ADD HERE ==>
});
},
hint: const Text("Grade"),
decoration: const InputDecoration(
border: OutlineInputBorder(),
contentPadding: EdgeInsets.only(left: 8),
),
),
),
Hi I have created a default form field, in a separate dart file called components, and I have login_screen.dart also.
there are many errors I don't know how to fix it, and make the code work, I will put down the code of the component.dart code:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
Widget defaultButton(
{double width = double.infinity,
Color background = Colors.blue,
double radius = 10.0,
required Function function,
required String text,
bool isUpperCase = true}) =>
Container(
height: 40.0,
width: width,
child: MaterialButton(
onLongPress: () {},
onPressed: function(),
child: Text(
isUpperCase ? text.toUpperCase() : text.toLowerCase(),
style: TextStyle(color: Colors.white),
)),
decoration: BoxDecoration(
borderRadius: BorderRadiusDirectional.circular(radius),
color: background,
),
);
Widget defaultFormFeild({
required TextEditingController controller,
required TextInputType type,
Function onSubmit,
Function onChange,
required Function validate,
required var label,
required IconData prefix,
}) =>
TextFormField(
controller: controller,
keyboardType: type,
onFieldSubmitted: onSubmit(),
onChanged: onChange(),
validator: validate(),
decoration: InputDecoration(
labelText: label,
prefixIcon: Icon(prefix),
border: OutlineInputBorder()
),
);
and here is the code of the login_screen.dart:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:udemy_flutter/shared/components/components.dart';
class LoginScreen extends StatelessWidget {
var emailController = TextEditingController();
var passController = TextEditingController();
var formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Padding(
padding: const EdgeInsets.all(20.0),
child: Center(
child: SingleChildScrollView(
child: Form(
key: formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Login',
style: TextStyle(
fontSize: 40.0,
fontWeight: FontWeight.bold
),
),
const SizedBox(
height: 40.0,
),
defaultFormFeild(
controller: emailController,
label: 'Email',
prefix: Icons.email,
type: TextInputType.emailAddress,
validate: (String value){
if(value.isEmpty != null){
return 'Email Cannot Be Empty';
}
return null;
}
),
const SizedBox(
height: 15.0,
),
TextFormField(
controller: passController,
obscureText: true,
keyboardType: TextInputType.visiblePassword,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Password',
prefixIcon: Icon(
Icons.lock
),
suffixIcon: Icon(
Icons.remove_red_eye,
)
),
onChanged: (value) {
print(value);
},
onFieldSubmitted: (value) {
print(value);
},
validator: (value) {
if(value!.isEmpty){
return 'Password cannot be empty';
}
return null;
},
),
const SizedBox(
height: 10.0,
),
defaultButton(
function: (){
print(emailController.text);
print(passController.text);
},
text: 'Login',
),
const SizedBox(
height: 10.0,
),
defaultButton(
text: 'ReGister',
function: () {
print('You have just clicked on register');
},
background: Colors.red,
isUpperCase: false
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('Don\'t you have an account?'),
TextButton(onPressed: () {}, child: const Text(
'Register Now'
))
],
)
],
),
),
),
),
),
);
}
}
Idk if all the problems came from a null-safety feature in a flutter because I'm new in this technology.
Why
The reason this happens is because with null safety enabled, your functions onSubmit and onChange can't be null.
Solution
I would do it this way:
Widget defaultFormFeild({
required TextEditingController controller,
required TextInputType type,
Function? onSubmit, //Add question mark
Function? onChange, //Add question mark
required Function validate,
required var label,
required IconData prefix,
}) =>
TextFormField(
controller: controller,
keyboardType: type,
onFieldSubmitted: onSubmit != null? onSubmit() : null, //do null checking
onChanged: onChange != null? onChange() : null, //do null checking
validator: validate(),
decoration: InputDecoration(
labelText: label,
prefixIcon: Icon(prefix),
border: OutlineInputBorder()
),
);
i got a problem while trying to make a form validator on my login screen it just doesn t work when i tape login and the text field is already null. here s my code if u have any help, i m down to :
TextFormField validate parameter takes a function that returns null if the content of the field is valid, or a string if the content is invalid. I have null safety in my flutter project and I can't return null from my validate function. How can I write a working validate function with null safety on?
Login code screen :
import 'package:flutter/material.dart';
import 'package:flutter_udemy/shared/components/components.dart';
class LoginScreen extends StatefulWidget {
LoginScreen({Key? key}) : super(key: key);
#override
_LoginScreenState createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
var emailController = TextEditingController();
var passwordController = TextEditingController();
var formKey = GlobalKey<FormState>();
bool isPassword = true;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Padding(
padding: const EdgeInsets.all(20.0),
child: Center(
child: SingleChildScrollView(
child: Form(
key: formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Login',
style: TextStyle(
fontSize: 40.0,
fontWeight: FontWeight.bold,
),
),
SizedBox(
height: 40.0,
),
defaultFormField(
controller: emailController,
label: 'Email',
prefix: Icons.email,
type: TextInputType.emailAddress,
validate: (String value) {
if (value.isEmpty) {
return 'email must not be empty';
}
return null;
},
),
SizedBox(
height: 15.0,
),
defaultFormField(
controller: passwordController,
label: 'Password',
prefix: Icons.lock,
suffix:
isPassword ? Icons.visibility : Icons.visibility_off,
isPassword: isPassword,
suffixPressed: () {
setState(() {
isPassword = !isPassword;
});
},
type: TextInputType.visiblePassword,
validate: (String value) {
if (value.isEmpty) {
return 'password is too short';
}
return null;
},
),
SizedBox(
height: 20.0,
),
defaultButton(
text: 'login',
function: () {
if (formKey.currentState!.validate()) {
print(emailController.text);
print(passwordController.text);
}
},
),
SizedBox(
height: 20.0,
),
defaultButton(
text: 'ReGIster',
function: () {
print(emailController.text);
print(passwordController.text);
},
),
SizedBox(
height: 10.0,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Don\'t have an account?',
),
TextButton(
onPressed: () {},
child: Text(
'Register Now',
),
),
],
),
],
),
),
),
),
),
);
}
}
componenents code screen where i got the button widget and text field widget:
import 'package:flutter/material.dart';
Widget defaultButton({
double width = double.infinity,
Color background = Colors.blue,
bool isUpperCase = true,
double radius = 10.0,
required Function function,
required String text,
}) =>
Container(
width: width,
height: 50.0,
child: MaterialButton(
onPressed: () {
function();
},
child: Text(
isUpperCase ? text.toUpperCase() : text,
style: TextStyle(
color: Colors.white,
),
),
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(
radius,
),
color: background,
),
);
Widget defaultFormField({
required TextEditingController controller,
required TextInputType type,
Function? onSubmit,
Function? onChange,
bool isPassword = false,
required Function validate,
required String label,
required IconData prefix,
IconData? suffix,
Function? suffixPressed,
}) =>
TextFormField(
controller: controller,
keyboardType: type,
obscureText: isPassword,
onFieldSubmitted: (s) {
onSubmit!(s);
},
onChanged: (s) {
onChange!(s);
},
validator: (s) {
validate(s);
},
decoration: InputDecoration(
labelText: label,
prefixIcon: Icon(
prefix,
),
suffixIcon: suffix != null
? IconButton(
onPressed: () {
suffixPressed!();
},
icon: Icon(
suffix,
),
)
: null,
border: OutlineInputBorder(),
),
);
This code works
Main changes done for null safety
required String? Function(String?)? validate
validate: (String? value) {
if (value!.isEmpty)
{
return 'email must not be empty';
}
return null;
},
Full code below
class LoginScreen extends StatefulWidget {
LoginScreen({Key? key}) : super(key: key);
#override
_LoginScreenState createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
var emailController = TextEditingController();
var passwordController = TextEditingController();
final formKey = GlobalKey<FormState>();
bool isPassword = true;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Padding(
padding: const EdgeInsets.all(20.0),
child: Center(
child: SingleChildScrollView(
child: Form(
key: formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Login',
style: TextStyle(
fontSize: 40.0,
fontWeight: FontWeight.bold,
),
),
SizedBox(
height: 40.0,
),
defaultFormField(
controller: emailController,
label: 'Email',
prefix: Icons.email,
type: TextInputType.emailAddress,
validate: (String? value) {
if (value!.isEmpty) {
return 'email must not be empty';
}
return null;
},
),
SizedBox(
height: 15.0,
),
defaultFormField(
controller: passwordController,
label: 'Password',
prefix: Icons.lock,
suffix:
isPassword ? Icons.visibility : Icons.visibility_off,
isPassword: isPassword,
suffixPressed: () {
setState(() {
isPassword = !isPassword;
});
},
type: TextInputType.visiblePassword,
validate: (String? value) {
if (value!.isEmpty) {
return 'password is too short';
}
return null;
},
),
SizedBox(
height: 20.0,
),
defaultButton(
text: 'login',
function: () {
if (formKey.currentState!.validate()) {
print(emailController.text);
print(passwordController.text);
}
},
),
SizedBox(
height: 20.0,
),
defaultButton(
text: 'ReGIster',
function: () {
print(emailController.text);
print(passwordController.text);
},
),
SizedBox(
height: 10.0,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Don\'t have an account?',
),
TextButton(
onPressed: () {},
child: Text(
'Register Now',
),
),
],
),
],
),
),
),
),
),
);
}
Widget defaultButton({
double width = double.infinity,
Color background = Colors.blue,
bool isUpperCase = true,
double radius = 10.0,
required Function function,
required String text,
}) =>
Container(
width: width,
height: 50.0,
child: MaterialButton(
onPressed: () {
function();
},
child: Text(
isUpperCase ? text.toUpperCase() : text,
style: TextStyle(
color: Colors.white,
),
),
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(
radius,
),
color: background,
),
);
}
Widget defaultFormField({
required TextEditingController controller,
required TextInputType type,
Function? onSubmit,
Function? onChange,
bool isPassword = false,
required String? Function(String?)? validate,
required String label,
required IconData prefix,
IconData? suffix,
Function? suffixPressed,
}) =>
TextFormField(
controller: controller,
keyboardType: type,
obscureText: isPassword,
onFieldSubmitted: (s) {
onSubmit!(s);
},
onChanged: (s) {
onChange!(s);
},
validator: validate,
decoration: InputDecoration(
labelText: label,
prefixIcon: Icon(
prefix,
),
suffixIcon: suffix != null
? IconButton(
onPressed: () {
suffixPressed!();
},
icon: Icon(
suffix,
),
)
: null,
border: OutlineInputBorder(),
),
);
you can try this one
validate: (String? value) {
if (value == null || value.trim().isEmpty) {
return 'Please provide a value.';
}
return null;
}
I am still new to Flutter.In here i want to select the value from a drop down list to the category form field.But i get a error when trying to define
child: DropdownButtonHideUnderline
inside Textformfield.I try to find a solution, but I can't find it and I am not able to program it by myself. I hope you can help me.Is there any other way to archive this?
my codes are here, Thanks in advance for your guidance.
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
final AuthService _auth = AuthService();
final _formKey = GlobalKey<FormState>();
String error = '';
bool loading = false;
String name = '';
String nickname = '';
String city = '';
#override
Widget build(BuildContext context) {
return Container(
child: Scaffold(
backgroundColor: Colors.brown[50],
appBar: AppBar(
title: Text('Brew Crew'),
backgroundColor: Colors.brown[400],
elevation: 0.0,
actions: <Widget>[
FlatButton.icon(
icon: Icon(Icons.person),
label: Text('logout'),
onPressed: () async {
await _auth.signOut();
},
),
],
),
body: Container(
padding: EdgeInsets.symmetric(vertical: 20.0, horizontal: 50.0),
child: Form(
key: _formKey,
child: SingleChildScrollView(
child: Column(
children: <Widget>[
SizedBox(height: 20.0),
TextFormField(
decoration: textInputDecoration.copyWith(hintText: 'Name'),
validator: (val) => val.isEmpty ? 'Enter your name' : null,
onChanged: (val) {
setState(() => name = val);
},
),
SizedBox(height: 20.0),
TextFormField(
decoration: textInputDecoration.copyWith(hintText: 'NickName'),
onChanged: (val) {
setState(() => nickname = val);
},
),
SizedBox(height: 20.0),
TextFormField(
decoration: textInputDecoration.copyWith(hintText: 'City'),
validator: (val) => val.isEmpty ? 'Enter your city' : null,
onChanged: (val) {
setState(() => city = val);
},
),
SizedBox(height: 20.0),
TextFormField(
decoration: textInputDecoration.copyWith(hintText: 'Category'),
validator: (val) => val.isEmpty ? 'Please select a category' : null,
onChanged: (val) {
setState(() => nickname = val);
},
),
SizedBox(height: 20.0),
RaisedButton(
color: Colors.pink[400],
child: Text(
'Submit',
style: TextStyle(color: Colors.white),
),
onPressed: () async {
}
),
SizedBox(height: 12.0),
Text(
error,
style: TextStyle(color: Colors.red, fontSize: 14.0),
)
],
),
),
),
),
),
);
}
}
The problem here is that you do not need a TextFormField, you would require a DropdownButton Widget.
DropdownButton(
items: <DropdownMenuItem>[
DropdownMenuItem(
child: Text("Category I"),
),
DropdownMenuItem(
child: Text("Category II"),
),
],
onChanged: (value) {
},
),
I created you a codepen for that:
https://codepen.io/md-weber/pen/zYvqaGv