Clear textfield based onchanged (flutter) - flutter

TextField(
inputFormatters: [
new FilteringTextInputFormatter.allow(
RegExp('[0-9]')),
],
hintText: 'some text'
title: '',
editingController: controllers[31],
value: somenumber,
onChange: (value) {
if (num.parse(value) <= 3000 &&
num.parse(value) >= 30) {
// save some data
}else{
controllers[31].clear(),
},
),
so above is a textfield with onchange, right now the textfield does not clear if i put outside of the range, is it possible to clear the textfield based onchange?

Is the TextField() you are using part of a plugin? The properties look a bit odd compared with the latest stable release of Flutter.
Here's an example that clears the text:
TextEditingController textEditingController = new TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Container(
child: TextField(
inputFormatters: [
new FilteringTextInputFormatter.allow(RegExp('[0-9]')),
],
decoration: InputDecoration(
hintText: 'some text',
),
controller: textEditingController,
onChanged: (value) {
if (value.length <= 10) {
// something
} else {
textEditingController.clear();
}
}
),
),
);
}

Create TextEditingController for your text field and then assign it to the controller property of TextField.
// create controller
TextEditingController _controller = new TextEditingController();
// assign it to TextField controller property
TextField(
controller : _controller
// your other properties
)
then to clear the text
// clear text
_controller.clear();
``

U can also do this :
TextEditingController textEditingController = new TextEditingController();
Function onchange;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Container(
child: TextField(
inputFormatters: [
new FilteringTextInputFormatter.allow(RegExp('[0-9]')),
],
decoration: InputDecoration(
hintText: 'some text',
suffixIcon: IconButton(
onPressed: () {
widget.onchanged('');
controller.clear();
},
),
controller: textEditingController,
onChanged: (value) => onchange(value)
}
),
),
);
}

Related

Flutter Text Form Field

i want to hide the second text form field if the first starts with a
if i write any word in the first text form field that starts with a the second disappear
TextFormField(
controller: firstColorController,
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(checkFirstColor(query.trim())){
return cubit.errorMessage;
}
},
),
const SizedBox(height: 15,),
if(firstColorController.text.startsWith("a"))
TextFormField(
controller: secondColorController,
decoration:const InputDecoration(
border: OutlineInputBorder(),
hintText: "second color"
),
validator: (value){
if(value!.isEmpty){
return "value can't be empty";
}
return null;
},
),
Here's an example.
bool secondVisible = true;
TextEditingController firstCtl = TextEditingController();
TextEditingController secondCtl = TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
children: [
TextFormField(controller: firstCtl, onChanged: (){
setState(() {
secondVisible = firstCtl.text.startsWith('a');
});
},),
Visibility(
visible: secondVisible,
child: TextFormField(controller: secondCtl)
),
],
),
),
);
}

TextFormField cursor did not move when changes occur

I have a screen that shows a textformfield, I want to retrieve the value that the user has inputted. But when I made a change the cursor didn't move, so it stays at position 0. How do I solve this problem?
class ScreenFormArtikel extends StatefulWidget {
final String mode;
ScreenFormArtikel(this.mode);
#override
_ScreenFormArtikelState createState() => _ScreenFormArtikelState();
}
class _ScreenFormArtikelState extends State<ScreenFormArtikel> {
var _key = GlobalKey<FormState>();
var _titleController = TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Article'),
),
body: Container(
child: Form(
key: _key,
child: Column(
children: [
Consumer<ProviderArtikel>(
builder: (context, artikel, child) {
return TextFormField(
decoration: InputDecoration(
labelText: 'Title',
floatingLabelBehavior: FloatingLabelBehavior.always),
controller: _titleController,
validator: (value) {
if (value.isEmpty) {
return "Please fill this field";
}
return null;
},
onChanged: (value) {
_titleController.text = value;
},
);
},
),
RaisedButton(onPressed: () {}),
],
),
),
),
);
}
}
I have attached the sample video below
click here
Commenting the onChanged will do the work.
TextFormField(
decoration: InputDecoration(
labelText: 'Title',
floatingLabelBehavior: FloatingLabelBehavior.always),
controller: _titleController,
validator: (value) {
if (value.isEmpty) {
return "Please fill this field";
}
return null;
},
// onChanged: (value) {
// _titleController.text = value;
// },
),
Actually the _titleController.text is setting the text onChange, that's why cursor is moving to the first place.
And you don't have to explicitly do the onTextChange thing.

How to validate form if at least n TextFormField are filled and retrieve their value in Flutter?

I have three different TextFormFields inside a Form, but only two of them can be filled at the same time.What I would like to achieve, is that whenerver two of them are filled, the other one should not be enabled.
They should be aware of changes in other fields at any time.
Below them is a RaisedButton that should be enabled when this condition is met.
Moreover, I need to do some logic with their values when the said button is pressed.
This is what I have right now:
class LPFilterCalculator extends StatefulWidget {
#override
State<StatefulWidget> createState() => _LPFilterCalculatorState();
}
class _LPFilterCalculatorState extends State<LPFilterCalculator> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: PersistentAppBar("Low Pass Filter").build(context),
drawer: DrawerMenu(),
body: Column(
children: <Widget>[
LowPassInputForm(),
],
),
);
}
}
/// Inputform class for Calculators
class LowPassInputForm extends StatefulWidget {
#override
State<StatefulWidget> createState() => _LowPassInputFormState();
}
class _LowPassInputFormState extends State<LowPassInputForm> {
ValueNotifier<bool> pressed = ValueNotifier(false);
final _formKey = GlobalKey<FormState>();
final resistanceTextController = TextEditingController();
final capacitorTextController = TextEditingController();
final frequencyTextController = TextEditingController();
#override
Widget build(BuildContext context) {
print('state update');
return Form(
onChanged: () => {},
key: _formKey,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: <Widget>[
Column(
children: <Widget>[
TextFormField(
controller: resistanceTextController,
inputFormatters: <TextInputFormatter>[
WhitelistingTextInputFormatter.digitsOnly
],
keyboardType: TextInputType.number,
decoration:
const InputDecoration(hintText: 'Enter resistance value'),
),
TextFormField(
controller: capacitorTextController,
inputFormatters: <TextInputFormatter>[
WhitelistingTextInputFormatter.digitsOnly
],
keyboardType: TextInputType.number,
decoration:
const InputDecoration(hintText: 'Enter capacitor value'),
),
TextFormField(
controller: frequencyTextController,
inputFormatters: <TextInputFormatter>[
WhitelistingTextInputFormatter.digitsOnly
],
keyboardType: TextInputType.number,
decoration: const InputDecoration(
hintText: 'Enter desired cutoff frequency'),
),
RaisedButton(
elevation: 5.0,
onPressed: () {
calculateLowPass();
},
),
],
),
],
),
),
);
}
void calculateLowPass() {
var resistance = resistanceTextController.text;
var capacitor = capacitorTextController.text;
var frequency = frequencyTextController.text;
// do calculations
}
#override
void dispose() {
frequencyTextController.dispose();
super.dispose();
}
}
You should note I'm not really using some properties as well as functionalities of objects, as I'm not really sure which is the correct or best way to approach this in Flutter.
Any tips would be more than welcomed!
i am sure there are better way of doing it, but here is how i did it, i used the enabled property on TextFormField and created a method for each one that take the controller of the other two TextFormField, i also created one for the button to check the all the text form fields, here is the full code:
/// Inputform class for Calculators
class LowPassInputForm extends StatefulWidget {
#override
State<StatefulWidget> createState() => _LowPassInputFormState();
}
class _LowPassInputFormState extends State<LowPassInputForm> {
ValueNotifier<bool> pressed = ValueNotifier(false);
final _formKey = GlobalKey<FormState>();
bool isEnabled = true;
final resistanceTextController = TextEditingController();
final capacitorTextController = TextEditingController();
final frequencyTextController = TextEditingController();
bool checkResistanceController() =>
frequencyTextController.text.isEmpty ||
capacitorTextController.text.isEmpty;
bool checkCapacitorController() =>
frequencyTextController.text.isEmpty ||
resistanceTextController.text.isEmpty;
bool checkFrequencyController() =>
resistanceTextController.text.isEmpty ||
capacitorTextController.text.isEmpty;
bool enableButton() =>
!checkFrequencyController() ||
!checkCapacitorController() ||
!checkResistanceController();
#override
Widget build(BuildContext context) {
print('state update');
return Form(
onChanged: () => setState(() {
checkResistanceController();
}),
key: _formKey,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: <Widget>[
Column(
children: <Widget>[
TextFormField(
enabled: checkResistanceController(),
controller: resistanceTextController,
inputFormatters: <TextInputFormatter>[
WhitelistingTextInputFormatter.digitsOnly
],
keyboardType: TextInputType.number,
decoration:
const InputDecoration(hintText: 'Enter resistance value'),
),
TextFormField(
enabled: checkCapacitorController(),
controller: capacitorTextController,
inputFormatters: <TextInputFormatter>[
WhitelistingTextInputFormatter.digitsOnly
],
keyboardType: TextInputType.number,
decoration:
const InputDecoration(hintText: 'Enter capacitor value'),
),
TextFormField(
enabled: checkFrequencyController(),
controller: frequencyTextController,
inputFormatters: <TextInputFormatter>[
WhitelistingTextInputFormatter.digitsOnly
],
keyboardType: TextInputType.number,
decoration: const InputDecoration(
hintText: 'Enter desired cutoff frequency'),
),
RaisedButton(
elevation: 5.0,
onPressed:
enableButton() ? () => calculateLowPass() : null),
],
),
],
),
),
);
}
void calculateLowPass() {
var resistance = resistanceTextController.text;
var capacitor = capacitorTextController.text;
var frequency = frequencyTextController.text;
// do calculations
}
#override
void dispose() {
frequencyTextController.dispose();
super.dispose();
}
}
You need to use the enabled property on the TextFormField and check whether the other two fields are empty. If any of the fields is empty then you enable the current field.
You could save your data in an Object model:
class Object {
// for the sake of this example the fields here are strings, but in practice it's better to change them to double
String resistance;
String capacitor;
String frequency;
Object({
this.resistance = '',
this.capacitor = '',
this.frequency = '',
});
}
Your updated state looks like this with the added Object instance:
class _LowPassInputFormState extends State<LowPassInputForm> {
final _formKey = GlobalKey<FormState>();
final resistanceTextController = TextEditingController();
final capacitorTextController = TextEditingController();
final frequencyTextController = TextEditingController();
Object data = Object();
#override
Widget build(BuildContext context) {
return Form(
onChanged: () => {},
key: _formKey,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: <Widget>[
Column(
children: <Widget>[
TextFormField(
enabled: data.capacitor.isEmpty || data.frequency.isEmpty,
onChanged: (val) => setState(() => data.resistance = val),
controller: resistanceTextController,
inputFormatters: <TextInputFormatter>[
WhitelistingTextInputFormatter.digitsOnly
],
keyboardType: TextInputType.number,
decoration:
const InputDecoration(hintText: 'Enter resistance value'),
),
TextFormField(
enabled: data.resistance.isEmpty || data.frequency.isEmpty,
onChanged: (val) => setState(() => data.capacitor = val),
controller: capacitorTextController,
inputFormatters: <TextInputFormatter>[
WhitelistingTextInputFormatter.digitsOnly
],
keyboardType: TextInputType.number,
decoration:
const InputDecoration(hintText: 'Enter capacitor value'),
),
TextFormField(
enabled: data.resistance.isEmpty || data.capacitor.isEmpty,
onChanged: (val) => setState(() => data.frequency = val),
controller: frequencyTextController,
inputFormatters: <TextInputFormatter>[
WhitelistingTextInputFormatter.digitsOnly
],
keyboardType: TextInputType.number,
decoration: const InputDecoration(
hintText: 'Enter desired cutoff frequency'),
),
RaisedButton(
elevation: 5.0,
onPressed: () {
calculateLowPass();
},
),
],
),
],
),
),
);
}
void calculateLowPass() {
// use data to do calculations
}
}

Flutter: How to dynamically hide an action in the AppBar?

I've got search input as title and clear button as actions in my AppBar:
AppBar(
actions: <Widget>[IconButton(icon: Icon(Icons.clear), onPressed: () => queryController.clear())],
title: TextField(
autofocus: true,
controller: queryController,
decoration: InputDecoration(
hintText: 'Search...',
),
),
),
How can I dynamically display a clear button depending on search field value?
Just add if (queryController.text.length > 0) before action you want to hide dynamically and add setState to onChanged method of the TextField, here is your code;
AppBar(
actions: <Widget>[
if (queryController.text.length > 0)
IconButton(
icon: Icon(Icons.clear),
onPressed: () => queryController.clear(),
)
],
title: TextField(
autofocus: true,
controller: queryController,
decoration: InputDecoration(
hintText: 'Search...',
),
onChanged: (value) {
setState(() {});
},
),
)
inside the StatefulWidget you can use setState and a bool field to track if the action is shown or not:
bool _shouldHideAction;
TextEditingController _textEditingController;
#override
void initState() {
_shouldHideAction = true;
_textEditingController = TextEditingController();
super.initState();
}
#override
void dispose() {
_textEditingController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: _shouldHideAction ? [] : [Icon(Icons.clear)],
title: Text('appbarTitle'),
),
body: TextField(
style: TextStyle(color: Colors.red),
controller: _textEditingController,
onChanged: (newValue) {
if (newValue.length > 0) {
setState(() {
_shouldHideAction = false;
});
} else {
setState(() {
_shouldHideAction = true;
});
}
},
),
);
}

How to disable mobile keyboard action key using Flutter?

I just need to disable the action button while the search query is empty. I'm not sure if this is possible with native Flutter.
Does this need to be done with each platform specifically? (iOS / Android)
You have a couple of options.
You can create a new focus:
FocusScope.of(context).requestFocus(new FocusNode())
Example:
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: GestureDetector(
onTap: () {
FocusScope.of(context).requestFocus(new FocusNode());
},
child: ....,
)
)
)
}
The other option is to release the existing focus:
FocusScopeNode currentFocus = FocusScope.of(context);
if (!currentFocus.hasPrimaryFocus) {
currentFocus.unfocus();
}
There is also a package: keyboard_dismisser
You just need to add a FocusNode to your TextFormField and request focus for it if the user presses the submit button on the keyboard when the field is empty. Here is a complete example:
class KeyboardKeeper60943209 extends StatefulWidget {
#override
_KeyboardKeeper60943209State createState() => _KeyboardKeeper60943209State();
}
class _KeyboardKeeper60943209State extends State<KeyboardKeeper60943209> {
List<String> items = List.generate(20, (index) => 'item $index');
TextEditingController _textEditingController = TextEditingController();
FocusNode _focusNode = FocusNode();
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Row(
children: <Widget>[
Expanded(
child: TextFormField(
focusNode: _focusNode,
controller: _textEditingController,
decoration: InputDecoration(
prefixIcon: Icon(Icons.search),
labelText: 'Search',
hasFloatingPlaceholder: false,
),
// This is the key part
onFieldSubmitted: (value) {
if(value == ''){
_focusNode.requestFocus();
}
},
),
),
FlatButton(onPressed: search, child: Text('Search'))
],
),
Expanded(
child: Container(
child: ListView.builder(
itemBuilder: (context, index){
return ListTile(
title: Text(items[index]),
subtitle: Text(items[index]),
);
}
),
),
),
],
);
}
void search(){
print('search');
}
}
TextFormField(
readOnly: true,
showCursor: false,
controller: consName,
decoration: InputDecoration(
hintText: 'Enter Name',
labelText: 'Username',
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.deepPurple,
width: 2,
),
),
),
),
Very Simple & Easy Use "readOnly: true" for disabling keyboard and if you don't want pointer or cursor then "showCursor: false". That's it, hope this'll work. Eat Sleep Workout Code Repeat. Happy Coding😊.
You can simply use textInputAction: TextInputAction.none on the TextField.