Home > Mobile >  "onSaved()" function in TextFormField not being reached (dart/flutter)
"onSaved()" function in TextFormField not being reached (dart/flutter)

Time:04-05

I have built a very simple form in flutter and I am trying to save the value of whatever is typed in the form fields to variables. This way, I can push these variables to firebase. However, nothing in the onSaved() block of the TextFormFields is being run. I have called save() on the current state of the form, but it still doesn't seem to work. Any ideas?

I have attached the code for the page below:

import 'package:flutter/material.dart';

class AddJobPage extends StatefulWidget {
  const AddJobPage({Key? key}) : super(key: key);

  static Future<void> show(BuildContext context) async {
    await Navigator.of(context).push(MaterialPageRoute(
        builder: (context) => const AddJobPage(),
      fullscreenDialog: true
    ));
  }

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

class _AddJobPageState extends State<AddJobPage> {
  final _formKey = GlobalKey<FormState>();

  //These two variables are where we will store the values of the text form fields
  //before we push to firestore.
  String? _name = '';
  int _ratePerHour = 0;


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        elevation: 2,
        title: const Text("New Job"),
        backgroundColor: Colors.teal.shade700,
        actions: [
          TextButton(
              onPressed: _submit,
              child: const Text(
                  'Save',
                style: TextStyle(fontSize: 18, color: Colors.white),
              )
          )
        ],
      ),
      body: _buildContents(),
      backgroundColor: Colors.grey.shade200,
    );
  }

  void _submit() {
    if(_validateAndSave()) {
      print("form saved, name: $_name, ratePerHour: $_ratePerHour");
    }
  }

  bool _validateAndSave() {
    final form = _formKey.currentState;
    if(form!.validate()) {
      print("the form was saved here");
      form.save;
      return true;
    }
    return false;
  }

  Widget _buildContents() {
    return SingleChildScrollView(
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Card(
          child: Padding(
            padding: const EdgeInsets.all(16),
            child: _buildForm(),
          ),
        ),
      ),
    );
  }

  Widget _buildForm() {
    return Form(
      key: _formKey,
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: _buildFormChildren(),
        )
    );
  }

  List<Widget> _buildFormChildren() {
    
    return [
      TextFormField(
        decoration: const InputDecoration(labelText: 'Job name'),
        onSaved: (value) {
          print("code doesn't reach here");
          _name = value; //save the value of the text field to _name
        }
      ),
      TextFormField(
        decoration: const InputDecoration(labelText: 'Rate Per Hour'),
        keyboardType: const TextInputType.numberWithOptions(
          signed: false,
          decimal: false
        ),
        onSaved: (value) {

          _ratePerHour = int.tryParse(value!) ?? 0;
        }
      ),
    ];
  }
}

CodePudding user response:

You need to call the save function.
So replace form.save; in your code with form.save();

CodePudding user response:

replace form.save with form.save() and you're done. No need to worry about text controllers since you're using a text form field

CodePudding user response:

you need to add a TextEditingController to get the text from a TextFormField. Then you need to call setstate inside OnChanged, not on Onsaved so you can transfer the text to a variable. This is what your code should look like:
First you initialize a controller like this

final TextEditingController textController = TextEditingController();
String _name = "not set";

then you add the controller to your textformfield like this

TextFormField(
            controller: textController ,
            onChanged:(value)
            {
              setState(() {
                _name = textController.text;
              });
            } ,
          )

This is a complete example:

class TextFormFieldExample extends StatefulWidget {
  const TextFormFieldExample({Key? key}) : super(key: key);

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

class _TextFormFieldExampleState extends State<TextFormFieldExample> {
  //Create the controller here
  final TextEditingController textController = TextEditingController();
  String _name = "not set";
  @override
  Widget build(BuildContext context) {
    print(_name);
    return Scaffold(
      body: Material(
        child: Container(
          color: Colors.white,
          height: MediaQuery.of(context).size.height,
          width: MediaQuery.of(context).size.width,
          child:TextFormField(
            controller: textController ,//Attach the controller to the text form here
            onChanged:(value)
            {
              setState(() {
                _name = textController.text;//Save the text from the controller to a variable
              });
            } ,
          ),

        ),
      ),
    );
  }
}
  • Related