How do you change the value inside of a textfield flutter?
FlutterDartFlutter Problem Overview
I have a TextEditingController
where if a user clicks a button it fills in with information. I can't seem to figure out how to change the text inside of a Textfield
or TextFormField
. Is there a solution?
Flutter Solutions
Solution 1 - Flutter
Simply change the text
property
TextField(
controller: txt,
),
RaisedButton(onPressed: () {
txt.text = "My Stringt";
}),
while txt
is just a TextEditingController
var txt = TextEditingController();
Solution 2 - Flutter
The problem with just setting
_controller.text = "New value";
is that the cursor will be repositioned to the beginning (in material's TextField). Using
_controller.text = "Hello";
_controller.selection = TextSelection.fromPosition(
TextPosition(offset: _controller.text.length),
);
setState(() {});
is not efficient since it rebuilds the widget more than it's necessary (when setting the text property and when calling setState).
--
I believe the best way is to combine everything into one simple command:
final _newValue = "New value";
_controller.value = TextEditingValue(
text: _newValue,
selection: TextSelection.fromPosition(
TextPosition(offset: _newValue.length),
),
);
It works properly for both Material and Cupertino Textfields.
Solution 3 - Flutter
Screenshot:
-
Create a
TextEditingController
:final TextEditingController _controller = TextEditingController();
-
Assign it to your
TextField
orTextFormField
:TextField(controller: _controller)
-
To update the text using a button at the cursor position (imagine there is already text in the textfield) :
ElevatedButton( onPressed: () { const newText = 'Hello World'; final updatedText = _controller.text + newText; _controller.value = _controller.value.copyWith( text: updatedText, selection: TextSelection.collapsed(offset: updatedText.length), ); }, )
Solution 4 - Flutter
You can use the text editing controller to manipulate the value inside a textfield.
var textController = new TextEditingController();
Now, create a new textfield and set textController
as the controller for the textfield as shown below.
new TextField(controller: textController)
Now, create a RaisedButton
anywhere in your code and set the desired text in the onPressed
method of the RaisedButton
.
new RaisedButton(
onPressed: () {
textController.text = "New text";
}
),
Solution 5 - Flutter
_mytexteditingcontroller.value = new TextEditingController.fromValue(new TextEditingValue(text: "My String")).value;
This seems to work if anyone has a better way please feel free to let me know.
Solution 6 - Flutter
First Thing
TextEditingController MyController= new TextEditingController();
Then add it to init State or in any SetState
MyController.value = TextEditingValue(text: "ANY TEXT");
Solution 7 - Flutter
The issue does not appear if you use the StatefulWidget
with _controller
as a member. Sounds weird but moving from stateless to stateful worked fine (that's because the widget is redrawn on each input to text editing controller which does not preserve state) E.g.:
Stateful: (working)
class MyWidget extends StatefulWidget {
const MyWidget(
{Key? key})
: super(key: key);
@override
_MyWidgetState createState() =>
_MyWidgetState();
}
class _MyWidgetState
extends State<MyWidget> {
late TextEditingController _controller;
@override
void initState() {
super.initState();
_controller = TextEditingController(text: "My Text");
}
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextField(
controller: _controller,
),
],
);
}
}
Stateless: (issue)
class MyWidget extends StatelessWidget {
const MyWidget(
{Key? key})
: super(key: key);
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextField(
controller: TextEditingController(text: "My Text"),
),
],
);
}
}
Solution 8 - Flutter
If you simply want to replace the entire text inside the text editing controller, then the other answers here work. However, if you want to programmatically insert, replace a selection, or delete, then you need to have a little more code.
Making your own custom keyboard is one use case for this. All of the inserts and deletions below are done programmatically:
Inserting text
The _controller
here is a TextEditingController
for the TextField
.
void _insertText(String myText) {
final text = _controller.text;
final textSelection = _controller.selection;
final newText = text.replaceRange(
textSelection.start,
textSelection.end,
myText,
);
final myTextLength = myText.length;
_controller.text = newText;
_controller.selection = textSelection.copyWith(
baseOffset: textSelection.start + myTextLength,
extentOffset: textSelection.start + myTextLength,
);
}
Thanks to this Stack Overflow answer for help with this.
Deleting text
There are a few different situations to think about:
- There is a selection (delete the selection)
- The cursor is at the beginning (don’t do anything)
- Anything else (delete the previous character)
Here is the implementation:
void _backspace() {
final text = _controller.text;
final textSelection = _controller.selection;
final selectionLength = textSelection.end - textSelection.start;
// There is a selection.
if (selectionLength > 0) {
final newText = text.replaceRange(
textSelection.start,
textSelection.end,
'',
);
_controller.text = newText;
_controller.selection = textSelection.copyWith(
baseOffset: textSelection.start,
extentOffset: textSelection.start,
);
return;
}
// The cursor is at the beginning.
if (textSelection.start == 0) {
return;
}
// Delete the previous character
final newStart = textSelection.start - 1;
final newEnd = textSelection.start;
final newText = text.replaceRange(
newStart,
newEnd,
'',
);
_controller.text = newText;
_controller.selection = textSelection.copyWith(
baseOffset: newStart,
extentOffset: newStart,
);
}
Full code
You can find the full code and more explanation in my article Custom In-App Keyboard in Flutter.
Solution 9 - Flutter
-
Declare TextEditingController.
-
supply controller to the TextField.
-
user controller's text property to change the value of the textField.
follow this official solution to the problem
Solution 10 - Flutter
Here is a full example where the parent widget controls the children widget. The parent widget updates the children widgets (Text and TextField) with a counter.
To update the Text widget, all you do is pass in the String parameter. To update the TextField widget, you need to pass in a controller, and set the text in the controller.
main.dart:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Demo',
home: Home(),
);
}
}
class Home extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Update Text and TextField demo'),
),
body: ParentWidget());
}
}
class ParentWidget extends StatefulWidget {
@override
_ParentWidgetState createState() => _ParentWidgetState();
}
class _ParentWidgetState extends State<ParentWidget> {
int _counter = 0;
String _text = 'no taps yet';
var _controller = TextEditingController(text: 'initial value');
void _handleTap() {
setState(() {
_counter = _counter + 1;
_text = 'number of taps: ' + _counter.toString();
_controller.text = 'number of taps: ' + _counter.toString();
});
}
@override
Widget build(BuildContext context) {
return Container(
child: Column(children: <Widget>[
RaisedButton(
onPressed: _handleTap,
child: const Text('Tap me', style: TextStyle(fontSize: 20)),
),
Text('$_text'),
TextField(controller: _controller,),
]),
);
}
}
Solution 11 - Flutter
simply change the text or value
property of controller.
if you do not edit selection property cursor goes to first of the new text.
onPress: () {
_controller.value=TextEditingValue(text: "sample text",selection: TextSelection.fromPosition(TextPosition(offset: sellPriceController.text.length)));
}
or in case you change the .text property:
onPress: () {
_controller.text="sample text";
_controller.selection = TextSelection.fromPosition(TextPosition(offset:_controller.text.length));
}
in cases that do not matter to you just don't change the selection property