I have problems following step by step what happens when onChanged
is triggered on my TextField
. Especially, I have a problem understanding where and why the variable value gets its actual value in the following example.
Example:
class felder extends StatefulWidget {
felder({super.key});
String textFieldName = "";
@override
State<felder> createState() => _felderState();
}
class _felderState extends State<felder> {
@override
Widget build(BuildContext context) {
return Column(
children: [
TextField(
obscureText: false,
decoration: const InputDecoration(
border: OutlineInputBorder(), labelText: 'Name'),
onChanged: (value) => widget.textFieldName = value,
)
],
);
}
}
How I always imagined it: I think flutter passes a function
in the background, which has a parameter value, that has the content of the TextField
.
CodePudding user response:
- Actually
TextField
is a widget that has its own state. - Whenever user types something, the value in a
TextField
changes. - At that time, a callback is fired from the
TextField
. - The changed value is also passed along with the callback.
- Using
onChanged: (value){ print(value); }
, we can get the value from that callback and use it as per our needs.
From TextField
source code,
The text field calls the [onChanged] callback whenever the user changes the text in the field. If the user indicates that they are done typing in the field (e.g., by pressing a button on the soft keyboard), the text field calls the [onSubmitted] callback.
To get the value from a TextField
, you can also use TexteditingController
.
First declare TextEditingController controller = TextEditingController();
.
Then inside your TextField
, add the controller like this
TextField(
controller: controller,
),
Then to get the value from controller, you can use controller.value.text
.
CodePudding user response:
What is a callback?
From GeeksForGeeks:
Callback is basically a function or a method that we pass as an argument into another function or a method to perform an action. In the simplest words, we can say that Callback or VoidCallback are used while sending data from one method to another and vice-versa
Creating a callback
To create your own callback, you can use ValueChanged
.
Code example:
Let's create our own button, that when the onChanged
is called, it will give us a new value
:
class ButtonChange extends StatefulWidget {
final bool value;
final ValueChanged<bool> onChanged;
ButtonChange({Key? key, required this.value, required this.onChanged})
: super(key: key);
@override
State<ButtonChange> createState() => _ButtonChangeState();
}
class _ButtonChangeState extends State<ButtonChange> {
bool _isToggled = false;
void toggle() {
setState(() {
_isToggled = !_isToggled;
});
widget.onChanged(_isToggled);
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: toggle,
child: Container(
width: 100,
height: 100,
decoration: BoxDecoration(
color: _isToggled ? Colors.green : Colors.red,
borderRadius: BorderRadius.circular(50),
),
),
);
}
}
Usage:
class MyWidget extends StatefulWidget {
@override
State<MyWidget> createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
var _value = false;
@override
Widget build(BuildContext context) {
return Column(
children: [
ButtonChange(
value: _value,
onChanged: (bool value) => setState(() {
_value = value;
})),
Text('$_value')
],
);
}
}
Complete example
You can run/paste this example in your editor, and take a look:
const Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: darkBlue,
),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: MyWidget(),
),
),
);
}
}
class MyWidget extends StatefulWidget {
@override
State<MyWidget> createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
var _value = false;
@override
Widget build(BuildContext context) {
return Column(
children: [
ButtonChange(
value: _value,
onChanged: (bool value) => setState(() {
_value = value;
})),
Text('$_value')
],
);
}
}
class ButtonChange extends StatefulWidget {
final bool value;
final ValueChanged<bool> onChanged;
ButtonChange({Key? key, required this.value, required this.onChanged})
: super(key: key);
@override
State<ButtonChange> createState() => _ButtonChangeState();
}
class _ButtonChangeState extends State<ButtonChange> {
bool _isToggled = false;
void toggle() {
setState(() {
_isToggled = !_isToggled;
});
widget.onChanged(_isToggled);
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: toggle,
child: Container(
width: 100,
height: 100,
decoration: BoxDecoration(
color: _isToggled ? Colors.green : Colors.red,
borderRadius: BorderRadius.circular(50),
),
),
);
}
}
See also
How to pass callback in Flutter
CodePudding user response:
What's in onChanged Docs ?
ValueChanged<String>? onChanged
onChanged
is of typeValueChanged<String>
and is called when the user initiates a change to the TextField's value: when they have inserted or deleted text.
This callback doesn't run when the TextField's text
is changed programmatically, via the TextField's controller
. Typically it isn't necessary to be notified of such changes, since they're initiated by the app itself.
What is Callback ?
If we go by definition, the Callback
is a function
or a method
which we pass as an argument
into another function
or method
and can perform an action when we require it.
For Example, if you are working in any app and if you want any change in any value then what would you do?
Here you are in a dilemma that what you want to change either state()
or a simple value/values
. If you need to change states then you have various state-changing techniques but if you want to change simple values then you will use Callback
.
Refer this article to understand the callback on event of textChange this will surely make you understand the core behind the mechanism