skip to Main Content

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.

3

Answers


    • 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.

    Login or Signup to reply.
  1. 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

    Login or Signup to reply.
  2. What’s in onChanged Docs ?

    ValueChanged<String>? onChanged
    

    onChanged is of type ValueChanged<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

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search