43

everyone.

I am using Form and TextFieldForm without any own TextEditController. Have 3 TextFieldForm (Value_1, Value_2, Total) with initial values. When i am editing first one, the Total textfield should contain result of calculation . To update widget i am using setState. The problem that variable _total and Text widget always has a correct calculation value, but the Total textfield does not want to update.

why? is it posible to do without using own TextEditController?

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: TestForm(),
    );
  }
}

class TestForm extends StatefulWidget {
  @override
  _TestFormState createState() => _TestFormState();
}

class _TestFormState extends State<TestForm> {
  GlobalKey<FormState> _formKey = GlobalKey();

  int _value1 = 0;
  int _value2 = 20;
  int _total = 0;

  @override
  Widget build(BuildContext context) {
    print('rebuild');
    return Scaffold(
      appBar: AppBar(title: Text('test form')),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Form(
          key: _formKey,
          child: ListView(
            children: <Widget>[
              TextFormField(
                initialValue: _value1.toString(),
                decoration: InputDecoration(
                  labelText: 'Value_1',
                ),
                keyboardType: TextInputType.number,
                onChanged: (value) {
                  setState(() {
                    _total = int.parse(value) * _value2;
                    print('total: ' + _total.toString());
                  });
                },
              ),
              TextFormField(
                initialValue: _value2.toString(),
                keyboardType: TextInputType.number,
                 decoration: InputDecoration(
                  labelText: 'Value_2',
                ),
              ),
              TextFormField(
                initialValue: _total.toString(),
                keyboardType: TextInputType.number,
                 decoration: InputDecoration(
                  labelText: 'Total',
                ),
              ),
              SizedBox(height: 20),
              Text('total: ' + _total.toString()),
            ],
          ),
        ),
      ),
    );
  }
}


example

wondertalik
  • 658
  • 1
  • 6
  • 11
  • Because its just an initial value, it not the value you set to TextFormField, maybe setState only rebuild Widget but not the initial value of it. try this [link] (https://stackoverflow.com/questions/51715534/textformfield-flutter-not-changing-appropriately) – hoangquyy Sep 23 '19 at 02:27
  • 2
    no, it is not possible - use `controller` property instead of `initialValue` – pskink Sep 23 '19 at 06:21
  • btw what is wrong with using `TextEditController`? is your code more complex, not readable? – pskink Sep 23 '19 at 06:28
  • nothing wrong with TextEditController, but it´s a little bit strange for me use TextFormField with default controller without any easy option use this controller for managing values. 20 fields in form = 20 own controllers, it´s too complex. – wondertalik Sep 23 '19 at 08:13
  • Possible duplicate of [TextFormField Flutter not changing appropriately](https://stackoverflow.com/questions/51715534/textformfield-flutter-not-changing-appropriately) – TWL Oct 24 '19 at 18:09
  • You should add `Key` to your `TextFormField`. See this link https://stackoverflow.com/questions/58348965/flutter-textformfield-not-updating-value-on-rebuild – BambinoUA May 20 '20 at 14:51

2 Answers2

122

If you have a reactive data source, aka data that can change based on either network updates or other data, one hack that worked for me was to use a Key.

By making a Key of the reactive data (toString()), the form field will change every time the Key changes.

So in this case you could do:

TextFormField(
  key: Key(_total.toString()), // <- Magic!
  initialValue: _total.toString(),
  keyboardType: TextInputType.number,
  decoration: InputDecoration(
    labelText: 'Total',
  ),
),
duttaoindril
  • 1,329
  • 1
  • 8
  • 6
  • 5
    If you have multiple TextFormFields you could end up with a key collision. UniqueKey seems to be a solution. Updates are really slow, I'm updating every time the user moves an object. Using a controller doesn't really make a performance difference... – Reyn Dec 12 '21 at 19:26
5

I used something as simple as this:

TextFormField(
 controller:  TextEditingController()..text = '23232',
  keyboardType: TextInputType.number,
  decoration: InputDecoration(
    labelText: 'Total',
  ),
),
  • 1
    This is not the correct way to do this. It will not `dispose()` of the `TextEdiingController`. – Dan Syrstad Mar 22 '22 at 14:00
  • One way around this would be to [useTextEditingController](https://pub.dev/documentation/flutter_hooks/latest/flutter_hooks/useTextEditingController-constant.html) from flutter_hooks. – Petri Nov 22 '22 at 07:30