TextFormField validator is not getting a value passed to it?

353 Views Asked by At

I have a card game scoring application I am developing and I have one bug I can't seem to get figured out. Hoping someone here sees my error and or can point to potential fixes. I have an input like this where you can enter the score for each player for the round. It's nothing more than a column of rows with a Text() holding the players name and a TextFormField() to enter/edit the score.

Image showing the score input/edit dialog in the app

Here is the code for the row:

              child: TextFormField(
                key: Key(p.name),
                keyboardType: TextInputType.number,
                initialValue: p.getRoundScore(round)?.toString() ?? '',
                inputFormatters: [LengthLimitingTextInputFormatter(3)],
                validator: (value) {
                  print('validate => ${p.name} : $value');
                  int score = int.tryParse(value);
                  return (score == null && value != null) ? "Must be a number" : null;
                },
                onChanged: (value) {
                  print('onChange => ${p.name} : $value');
                  setState(() {
                    int score = int.parse(value);
                    if (round == 9) score *= 2; // Queens round
                    if (round == 10) score *= 3; // Kings round
                    p.updateScore(round, score);
                  });
                },
              ),

If I enter scores, like John =2, Hannah=1, Tias=2 and Eric=0 and then click the save button, I get the following output from my print()s:

I/flutter (32660): onChange => John : 2
I/flutter (32660): onChange => Hannah : 1
I/flutter (32660): onChange => Tias : 2
I/flutter (32660): onChange => Eric : 0
I/flutter (32660): validate => John :
I/flutter (32660): validate => Hannah :
I/flutter (32660): validate => Tias :
I/flutter (32660): validate => Eric :

And the validation output in the app shows errors for each field:

Image showing the same score entry dialog with the validation errors

[EDIT] Adding the code for the save button here for completeness:

   if (_formKey.currentState.validate()) {
      _formKey.currentState.save();
      debugPrint(playerToJson(players));
      Navigator.of(context).pop();
  }                                  }                                  

What am I missing here? I could try and remove the onChange and move to using a TextController but this would add complexity as you can have 3-6 players and I'd have to have multiple controllers for it to work...they also seemed like overkill for what I needed to do.

I'm not sure why the "value" passed to the validator() is always an empty string, is there something I am doing wrong? Is this a bug? Is there a better way to do this?

2

There are 2 best solutions below

0
On BEST ANSWER

ok, after a bunch more digging it appears that somehow having the onChange was causing my problem. Even though all the examples from Google and others show this as perfectly acceptable, when I comment out the onChange then the validator gets the proper value passed to it for each field. This actually works out fine because I really should do the work of saving out the value to my model only after I have validated the value, so I just moved that logic into the validator. Now all works like it should.

2
On

Maybe you should wrap all your TextFormFields with a Form-Widget using also a global key for managing the form. Please also see the step 1 in flutter validation tutorial