I am having a flutter TextFormField and i am already showing an error and outlined border color change to red when text is empty or null. What i want is to also show a suffixIcon
when TextFormField is empty
below is my code
class Login extends StatefulWidget {
const Login({Key? key}) : super(key: key);
@override
_LoginState createState() => _LoginState();
}
class _LoginState extends State<Login> {
final loginFormKey = GlobalKey<FormState>();
TextEditingController userNameController = TextEditingController();
FocusNode userNameFocusNode = FocusNode();
bool userNameHasFocus = false;
@override
void initState() {
super.initState();
}
@override
void dispose() {
super.dispose();
userNameController.dispose();
userNameFocusNode.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: SingleChildScrollView(
child: Center(
child: Form(
autovalidateMode: AutovalidateMode.onUserInteraction,
key: loginFormKey,
child: Column(
children: [
Container(
padding: const EdgeInsets.all(1),
margin: const EdgeInsets.only(top: 5, bottom: 5),
child: const Text(
"Welcome to my app",
textAlign: TextAlign.center,
)),
Container(
margin: const EdgeInsets.only(
top: 1, bottom: 2, right: 1, left: 10),
child: TextFormField(
focusNode: userNameFocusNode,
controller: userNameController,
decoration: InputDecoration(
labelText: "Please Enter Username",
border: OutlineInputBorder(),
),
validator: (phoneNo) {
if (phoneNo!.isEmpty) {
userNameFocusNode.requestFocus();
userNameHasFocus = true;
return "You must enter username";
} else {
userNameHasFocus = false;
return null;
}
},
)),
Container(
margin: const EdgeInsets.only(
top: 2, bottom: 1, right: 10, left: 10),
child: ElevatedButton(
onPressed: () {
if (loginFormKey.currentState!.validate()) {
print(proceed)
}
},
child: Text("Login"),
style: ElevatedButton.styleFrom(
shape: StadiumBorder(),
)))
],
)))),
);
}
}
The part that i am interested is below in validator
validator: (phoneNo) {
if (phoneNo!.isEmpty) {
userNameFocusNode.requestFocus();
userNameHasFocus = true;
return "You must enter username";
} else {
userNameHasFocus = false;
return null;
}
},
Where if phoneNo!.isEmpty
i should show something like this below
suffixIcon: Icon(Icons.error_outline_rounded, color: Colors.red)
CodePudding user response:
You can use a bool
to show the suffixIcon
.
bool showSuffix = false;
@override
void initState() {
super.initState();
userNameController.addListener(() {
if (userNameController.text.isEmpty) {
showSuffix = true;
} else {
showSuffix = false;
}
setState(() {});
});
}
///.........
/// aslo can be used [Visibility] widget
suffixIcon: showSuffix
? const Icon(Icons.error_outline_rounded,
color: Colors.red)
: null,
CodePudding user response:
You need to show the icon or hide it according to a condition if the TextFormField
is validated or not.
Remove autovalidateMode: AutovalidateMode.onUserInteraction
and add onChanged
method instead like this:
import 'package:flutter/material.dart';
class Login extends StatefulWidget {
const Login({Key? key}) : super(key: key);
@override
_LoginState createState() => _LoginState();
}
class _LoginState extends State<Login> {
final loginFormKey = GlobalKey<FormState>();
TextEditingController userNameController = TextEditingController();
FocusNode userNameFocusNode = FocusNode();
bool userNameHasFocus = false;
bool validated = true;
@override
void initState() {
super.initState();
}
@override
void dispose() {
super.dispose();
userNameController.dispose();
userNameFocusNode.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: SingleChildScrollView(
child: Center(
child: Form(
key: loginFormKey,
child: Column(
children: [
Container(
padding: const EdgeInsets.all(1),
margin: const EdgeInsets.only(top: 5, bottom: 5),
child: const Text(
"Welcome to my app",
textAlign: TextAlign.center,
)),
Container(
margin: const EdgeInsets.only(top: 1, bottom: 2, right: 1, left: 10),
child: TextFormField(
focusNode: userNameFocusNode,
controller: userNameController,
decoration: InputDecoration(
labelText: "Please Enter Username",
border: const OutlineInputBorder(),
suffixIcon: !validated ? const Icon(Icons.error_outline_rounded, color: Colors.red) : const SizedBox()),
validator: (phoneNo) {
if (phoneNo!.isEmpty) {
userNameFocusNode.requestFocus();
userNameHasFocus = true;
return "You must enter username";
} else {
userNameHasFocus = false;
return null;
}
},
onChanged: (value) {
if (value.isNotEmpty) {
setState(() {
validated = true;
loginFormKey.currentState!.validate();
});
}
},
)),
Container(
margin: const EdgeInsets.only(top: 2, bottom: 1, right: 10, left: 10),
child: ElevatedButton(
onPressed: () {
if (loginFormKey.currentState!.validate()) {
setState(() {
validated = loginFormKey.currentState!.validate();
});
} else {
setState(() {
validated = loginFormKey.currentState!.validate();
});
}
},
child: const Text("Login"),
style: ElevatedButton.styleFrom(
shape: const StadiumBorder(),
),
),
)
],
),
),
),
),
);
}
}
Happy coding!!