Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.4k views
in Technique[技术] by (71.8m points)

dart - FormKey current state in flutter equals null

So i'm having a form like this:

 Form(
                  key: formKey,
                  child: Column(
                    children: [
                      TextFormField(
                        validator: _validateForm,
                        cursorColor: Colors.black,
                        controller: _numberLocalsController,
                        keyboardType: TextInputType.number,
                        decoration: InputDecoration(
                            contentPadding: EdgeInsets.only(
                                left: 15, bottom: 11, top: 11, right: 15),
                            hintText: "numero di locali"),
                      ),
                      TextFormField(
                        validator: _validateForm,
                        cursorColor: Colors.black,
                        controller: _numberRoomsController,
                        keyboardType: TextInputType.number,
                        decoration: InputDecoration(
                            contentPadding: EdgeInsets.only(
                                left: 15, bottom: 11, top: 11, right: 15),
                            hintText: "numero stanze da letto"),
                      ),
                      TextFormField(
                        validator: _validateForm,
                        cursorColor: Colors.black,
                        keyboardType: TextInputType.number,
                        controller: _numberbathroomsController,
                        decoration: InputDecoration(
                            contentPadding: EdgeInsets.only(
                                left: 15, bottom: 11, top: 11, right: 15),
                            hintText: "n° bagni"),
                      ),
                    ],
                  )),

and i initialized the formKey outside the build method like this :

class _FilterPageState extends State<FilterPage> {
  final formKey = GlobalKey<FormState>();}

The idea is that there's a button that's clicked that just does the following :

final isValid = formKey.currentState.validate();
                  if (isValid) {
        
                    Navigator.pop(context, filterModel);
                  }

Now I get the error

Validate() was called on null

The formkey current context only has a value the first time i open the form. but when the navigator pops and i try to access the form again it gives the error.

question from:https://stackoverflow.com/questions/65849394/formkey-current-state-in-flutter-equals-null

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Salma,

I'm still not clear on where / why you're seeing the null error, since I don't have access to your full code.

So I'll just post my own code sample below and you can compare implementations and hopefully that leads you to an answer.

From my test code below, it should be possible to Navigator.pop from the form page back to a previous page and then Navigator.push back to the form page and use the formKey again, without a null error.

FormStateTestPage

  • Just a base page with a Scaffold

BasePage

  • StatefulWidget where you can click a button to Navigator.push to the form page (FilterPage).

FilterPage

  • the Form is here
  • with the code sample below the Form is using a locally defined form key (localKey)
  • you can push to this FilterPage, pop back to BasePage, and push again to FilterPage and there should be no null errors
  • if you need access to form state outside of FilterPage, then you must declare a form key above FilterPage and provide it as a constructor argument
  • for outside access, replace the foreignKey: null with foreignKey: foreignKey (which is defined in _BasePageState). Then you can access form state from BasePage.
  • the code below is capturing the return value from the Navigator.push / Navigator.pop to FilterPage & back. That is how the form value is being shown in BasePage. The key line is: nukeCodes = await Navigator.push<String>
  • if nukeCodes is not null after popping back to BasePage, a setState is called, rebuilding BasePage & displaying the nukeCodes value.
class FormStateTestPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Form State Test'),
      ),
      body: BasePage(),
    );
  }
}

class BasePage extends StatefulWidget {
  @override
  _BasePageState createState() => _BasePageState();
}

class _BasePageState extends State<BasePage> {
  Key foreignKey = GlobalKey<FormState>();
  String nukeCodes;

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Text('Nuke Codes:'),
        Text(nukeCodes ?? 'awaiting'),
        Center(
          child: RaisedButton(
            child: Text('Go to Form'),
            onPressed: () async {
              nukeCodes = await Navigator.push<String>(
                  context,
                  MaterialPageRoute(
                    builder: (context) => FilterPage(foreignKey: null)
                ) // pass null to have FilterPage use its own, self-defined formKey
                // pass in foreignKey to use a formKey defined ABOVE FilterPage
              );
              if (nukeCodes != null && nukeCodes.isNotEmpty) {
                print('Codes returned');
                setState(() {});
              }
            }
          ),
        ),
      ],
    );
  }
}

class FilterPage extends StatefulWidget {
  final GlobalKey<FormState> foreignKey;

  FilterPage({this.foreignKey});

  @override
  _FilterPageState createState() => _FilterPageState();
}

class _FilterPageState extends State<FilterPage> {
  final localKey = GlobalKey<FormState>();
  GlobalKey<FormState> formKey;

  @override
  void initState() {
    super.initState();
    if (widget.foreignKey != null) {
      formKey = widget.foreignKey;
      print('Form using foreignKey');
    }
    else {
      formKey = localKey;
      print('Form using localKey');
    }
  }

  @override
  Widget build(BuildContext context) {
    String codes;

    return Scaffold(
      body: SafeArea(
        child: Form(
          key: formKey,
          //key: widget.formKey,
          child: ListView(
            children: [
              TextFormField(
                decoration: InputDecoration(
                  labelText: 'Enter Nuclear Codes'
                ),
                onSaved: (val) => codes = val,
                validator: (value) {
                  if (value.isEmpty) {
                    return 'A value is required';
                  }
                  return null;
                },
              ),
              RaisedButton(
                child: Text('Submit'),
                onPressed: () {
                  if (formKey.currentState.validate()) {
                    formKey.currentState.save();
                    Navigator.pop(context, codes);
                  }
                },
              )
            ],
          ),
        ),
      ),
    );
  }
}

Anyways, hopefully you can compare/contrast your code base with above and find out what's causing the null error.

Best of luck.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...