Hello I would like to validate the textfieldinput of a user when the textfield loses it's focus. I could only change the focusstate with the FocusNode but couldnt listen to it.
Is there any way to listen to state changes of the FocusNode?
TextEditingController displayNameController = TextEditingController();
late FocusNode myFocusNode;
void initState() {
super.initState();
myFocusNode = FocusNode();
...
}
....
TextField(
focusNode: myFocusNode,
readOnly: currentview == 2 ? false : true,
textAlign: TextAlign.center,
textAlignVertical: TextAlignVertical.center,
decoration: InputDecoration(
isDense: true,
border: InputBorder.none,
//changeup!!
errorText: _displayNameValid ? null : 'Bad characters'
),
style: Theme.of(context).textTheme.bodyText2!.copyWith(
color: AppTheme.white70,
),
controller: displayNameController,
),
Related
** TextEditingController gstController =
TextEditingController(
text: snapshot.data![index].gSTNo.toString());
TextFormField(
controller: gstController,
decoration: InputDecoration(
hintText: 'Enter GST No',
border: InputBorder.none,
contentPadding:
const EdgeInsets.all(14),
),
),**
you can follow this example
TextEditingController textEditingController = TextEditingController();
TextFormField(
controller: textEditingController,
autovalidateMode: AutovalidateMode.onUserInteraction,
style: TextStyle(fontSize: 15),
decoration: FormFields.getInputDecoration('Email Id'),
);
the after api response you can set text to textformfield using TextEditingController like this
setState((){
textEditingController.text = snapshot.data![index].gSTNo.toString()
});
add it to init State or in any SetState
gstController.value = TextEditingValue(text: "ANY TEXT");
I need to change the keyboard dynamically. the keyboard starts in TextInputType.text, when the user types 3 letters it is switched to TextInputType.number and the user types 4 numbers. ex: ABC1234.
final _controller = TextEditingController();
TextFormField(
decoration: InputDecoration(
labelText: "code",
hintText: 'ABC1234'),
controller: _myController,
keyboardType: TextInputType.text,
),
To change your TextInputType dynamically, what you can do is:
final _controller = TextEditingController();
//Creating a variable to store the type and initializing it with the default text type.
var keyboardType = TextInputType.text;
TextFormField(
decoration: InputDecoration(
labelText: "code",
hintText: 'ABC1234'),
controller: _myController,
//Passing the variable created in here
keyboardType: keyboardType,
onChanged: (value) {
//Checking if the value's length is less than 4, if it is, it should be type `text`.
if(value.isEmpty || value.length < 4) {
setState(() => keyboardType = TextInputType.text);
} else {
//Else, it should be type `number`
setState(() => keyboardType = TextInputType.number);
}
}
),
The will change the keyboard type dynamically but it may not change the keyboard, and you may have to close and open the keyboard again.
You can use keyboardType like this. It will be for both numbers and letters.
keyboardType: TextInputType.visiblePassword
Here is your working code
The keyboard is also changed automatically
final _controller = TextEditingController();
late FocusNode myFocusNode = FocusNode();
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Center(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: TextFormField(
style: Theme.of(context).textTheme.bodyText2,
controller: _controller,
focusNode: myFocusNode,
textCapitalization: TextCapitalization.characters,
keyboardType: (_controller.text.length >= 3) ? TextInputType.number : TextInputType.name,
onChanged: (text) {
if (_controller.text != text.toUpperCase()) {
_controller.value = _controller.value.copyWith(text: text.toUpperCase());
}
if (_controller.text.length == 3){
setState(() {
myFocusNode.unfocus();
Future.delayed(const Duration(milliseconds: 50)).then((value) {
myFocusNode.requestFocus();
});
});
}
},
inputFormatters: [
FilteringTextInputFormatter.allow(
RegExp('[a-zA-Z0-9]'))
],
decoration: const InputDecoration(labelText: 'ABC1234')),
),
),
);
}
Output:
Declare a variable like your controller for keyboardtype, where keyboardtype is variable and TextInputTupe is it's datatype.
TextInputType keyboardtype = TextInputType.text;
now, check yout textformfield's String, If your string.length is greater than 3 then keyboard type is TextInputType.number
check the length into onchanged in textformfield
final _controller = TextEditingController();
TextInputType keyboardType = TextInputType.text;
TextFormField(
decoration: InputDecoration(
labelText: "code",
hintText: 'ABC1234'),
controller: _myController,
keyboardType: TextInputType.text,
onChanged: (value){
var inputText = _myController.text;
if(inputText.length>3){
keyBoardType = TextInputType.number;
}
}
),
It would be better if you use some regex to check your inputformat into the inputFormatters in your textformfield. if you don't know about inputformatters just google it.
I am developing a flutter e_commerce app, and in registration, the username should be unique, for that, we have an endpoint in API to check either the username is taken or not, my problem is with validation, I need to validate after user interaction, in flutter we have auto validate mode, but there is only(always, onUserInteraction) options, and I need the validation right after user interaction
The textFormField of the username input is
TextFormField(
cursorColor: Theme.of(context).primaryColor,
autovalidateMode: AutovalidateMode.onUserInteraction,
decoration: InputDecoration(
suffixIcon: SuffixIcon(),
labelText:
'Choose suitable name and relevant to your products',
hintText: 'SweetCandies',
labelStyle: TextStyle(color: Colors.black),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context).primaryColor,
),
),
),
validator: (value) {
if(value!.isNotEmpty){}
Provider.of<Store>(context).usernameExistence(value, 'no');
if(Provider.of<Store>(context).nameExistence){
return 'The Chosen name is already taken';
}
if (value.isEmpty) {
return 'Required';
}
},
onSaved: (value) {
Provider.of<Store>(context, listen: false)
.storeInformation['name'] = value!;
},
)
is there any way to active validator after user interaction???
You can attach a focusNode to TextField so whenever focus changes you can make an api call and validate the text
add this code and initState to your code
TextEditingController controller = TextEditingController();
FocusNode focusNode;
bool _hasInputError;
String errorText = "";
String text;
#override
void initState() {
super.initState();
focusNode = new FocusNode();
focusNode.addListener(() {
if (!focusNode.hasFocus) {
setState(() {
if(Provider.of<Store>(context).nameExistence){// your condition
_hasInputErro = true;
errorText = 'The Chosen name is already taken';
}// <-- else if condition ...
else{
_hasInputErro = false;
}
});
}
});
}
in TextFormField :
TextFormField(
focusNode: focusNode,// <-- add focusNode here
controller: controller,// <-- add controller here
cursorColor: Theme.of(context).primaryColor,
autovalidateMode: AutovalidateMode.onUserInteraction,
decoration: InputDecoration(
errorText: _hasInputError ? errorText : null, // <-- add this line to show errors
suffixIcon: SuffixIcon(),
labelText:
'Choose suitable name and relevant to your products',
hintText: 'SweetCandies',
labelStyle: TextStyle(color: Colors.black),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context).primaryColor,
),
),
),
// validator: ... , // <-- comment validator
onSaved: (value) {
Provider.of<Store>(context, listen: false)
.storeInformation['name'] = value!;
},
)
I need to know how to hide the hint text when I focus on the text field. This is my code:
class _ContactoState extends State<Contacto> {
FocusNode focusMsj;
#override
void initState() {
super.initState();
focusMsj = FocusNode();
focusMsj.addListener(() {
if (!focusMsj.hasFocus) {
FocusScope.of(context).requestFocus(focusMsj);
}
});
}
TextField(
focusNode: focusMsj,
hintText: focusMsj.hasFocus ? ' ' : 'Hint Text',)
return WillPopScope(
child: Listener(
onPointerUp: (e) {
focusMsj.hasFocus ? FocusScope.of(context).requestFocus(FocusNode()): '';
},
Thank you
For doing that matter you need to make something like that
class Play extends StatefulWidget {
#override
_PlayState createState() => _PlayState();
}
class _PlayState extends State<Play> {
FocusNode focusNode = FocusNode();
String hintText = 'Hello , iam Hint';
#override
void initState() {
// TODO: implement initState
super.initState();
focusNode.addListener(() {
if (focusNode.hasFocus) {
hintText = '';
} else {
hintText = 'Hello , iam Hint';
}
setState(() {});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(onPressed: () {
print(focusNode.hasFocus);
}),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextField(
focusNode: focusNode,
decoration: InputDecoration(
hintText: hintText,
),
),
TextField(
decoration: InputDecoration(
hintText: '!!',
),
),
],
),
),
);
}
}
Shortly i listened to TextField by its focusNode property . When TextField has focus i make hintText property equal empty String value
There is a property for that:
TextField(decoration: InputDecoration(hasFloatingPlaceholder: false));
Edit: The version above is deprecated, the new version is:
TextField(decoration: InputDecoration(floatingLabelBehavior: FloatingLabelBehavior.never,),),
One simple solution you can try is define labelText with FloatingBehavior.never
TextField(
decoration: InputDecoration(
labelText: "Search",
floatingLabelBehavior: FloatingLabelBehavior.never,
)
)
HintText will be shown when it is not focussed. On focus, hint text will disappear.
Simply, don't add the hintText in the InputDecoration and mention only the labelText: 'Label' alongside labelStyle if you want to change the style of the label.
TextField(
decoration: InputDecoration(
labelText: "Label",
labelStyle: TextStyle(
color: Colors.blueGrey,
),
floatingLabelBehavior: FloatingLabelBehavior.never,
)
)
My understanding is there is no way to implement it without custom code. Hiding hintText when focused with "border: InputBorder.none," gives perfect login widget example as FloatingLabelBehavior and having animated labelText just won't do. floatingLabelBehavior: FloatingLabelBehavior.never - helps in some situtations but not the exact thing we wanted. If you have labelText and hintText FloatingLabelBehavior.never is helpful to control hiding and showing hintText and animating labelText above the field. WIth custom code we have
String emailHintText = "E-mail";
on the top of state class. Then:
Container(
decoration: BoxDecoration(
border: Border.all(color: white),
borderRadius: BorderRadius.circular(5)),
child: Padding(
padding: EdgeInsets.all(10),
child:
Focus(
onFocusChange: (hasFocus) {
if (hasFocus) {
setState(() {});
emailHintText = "";
}
else {
setState(() {});
emailHintText = "E-mail";
}
},
child: TextFormField(
decoration: InputDecoration(
hintText: emailHintText,
border: InputBorder.none))));
Now, you should know that using setState is a bit costly operation and may not be the best option if not used for very important functionalities.
This works perfectly for me. Just add on InputDecoration ( floatingLabelBehavior: FloatingLabelBehavior.never) of TextField or TextFormField.
TextFormField( controller:_controller, decoration : InputDecoration( label: Text('Entrer your code here '), floatingLabelBehavior: FloatingLabelBehavior.never, ), );
I have the following TextField:
TextField(
decoration: InputDecoration(
labelStyle: TextStyle(
color: I_WANT_TO_CHANGE_THIS,
),
labelText: widget.label,
),
);
How do I change the color so that when it's inside the text field (a hint), it's GRAY, and when it's floating above the text field (being focused), it's BLACK.
Try using a FocusNode:
class _MyHomePageState extends State<MyHomePage> {
FocusNode _focusNode = FocusNode();
Color color;
#override
Widget build(BuildContext context) {
_focusNode.addListener(() {
setState(() {
color = _focusNode.hasFocus ? Colors.blue : Colors.red;
});
});
return Scaffold(
body: Center(
child: TextField(
focusNode: _focusNode,
decoration: InputDecoration(
labelText: 'Label',
labelStyle: TextStyle(
color: _focusNode.hasFocus ? Colors.blue : Colors.red,
)
),
autofocus: false,
),
)
);
}
}
Notice that in this particular example the textfield will always be in focus once selected, since there's only one textfield.