Home > Enterprise >  How to save Flutter TextFormField user input to a value?
How to save Flutter TextFormField user input to a value?

Time:01-15

I'm trying to learn Flutter and I'm confused.

I want to make a super simple text form and a button. The user enters text into the form, clicks the button, and the text prints to the console. How hard could this be? :-)

import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';

void main() => runApp(const Kabbalah());

class Kabbalah extends StatelessWidget {
  const Kabbalah({Key? key}) : super(key: key);

  static const String _title = 'Kabbalistic Numerology';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: _title,
      home: Scaffold(
          appBar: AppBar(
            title: const Text(_title),
          ),
          body: const Center(
            child: const FullNameField(),
          )
      ),
    );
  }
}

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

  @override
  State<StatefulWidget> createState() {
    return _FullNameState();
  }
}

class _FullNameState extends State<FullNameField> {

  @override
  Widget build(BuildContext context) {

    return Column(
      crossAxisAlignment: CrossAxisAlignment.center,
      children: <Widget>[
        Container(
          padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 16),
          child: TextFormField(
            decoration: const InputDecoration(
              border: UnderlineInputBorder(),
              labelText: 'Enter your full name (First Middle Last)',
            ),
            onSaved: (String? fullName) {
              debugPrint(fullName);
              // This optional block of code can be used to run
              // code when the user saves the form.
            },
          ),
        ),
        ElevatedButton(
          style: ElevatedButton.styleFrom(textStyle: const TextStyle(fontSize: 20)),
          onPressed: () {
            debugPrint('Clicked!');
            setState(() {
              _FullNameState.save(); // <-- problem is here
            });
          },
          child: const Text('Get Fortune'),
        ),
      ],
    );
  }
}

My code makes a nice little form and an adorable button.

enter image description here

When enter a name and click the button I see Clicked! in the console.

My plan is that after the user clicks the button we save the form state. Then onSaved() will execute and print the entered text to the console.

The problem seems to be in saving the form state after the user clicks the button. _fullNameState.save(); doesn't work because _fullNameState doesn't have a .save member. Don't we get .save from extending StatefulWidget?

Thanks in advance for your help.

CodePudding user response:

I have done your work. I have attached my Code Snippets below. Please check and try yourself. Hope it will help. I also attached Screenshots below.

main.dart Code Snippet -->>

import 'package:flutter/material.dart';
import 'package:test2/test3.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      initialRoute: TextFormFieldWidgetTest.id,
      routes: {
        TextFormFieldWidgetTest.id: (context) => TextFormFieldWidgetTest(),
      },
    );
  }
}

TextForm Field Code -->

import 'package:flutter/material.dart';

class TextFormFieldWidgetTest extends StatefulWidget {
  const TextFormFieldWidgetTest({Key? key}) : super(key: key);
  static final String id = "text_form_field";

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

class _TextFormFieldWidgetTestState extends State<TextFormFieldWidgetTest> {
  // * Form Key
  final _formKey = GlobalKey<FormState>();
  // * Editing Controller
  final TextEditingController firstNameController = TextEditingController();

  String? firstName;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Center(
          child: Padding(
            padding: const EdgeInsets.all(8.0),
            child: Column(
              children: [
                Form(
                  key: _formKey,
                  child: Container(
                    decoration: BoxDecoration(
                        color: const Color(0x0fffffff),
                        borderRadius: BorderRadius.circular(10)),
                    child: TextFormField(
                      style: const TextStyle(
                        color: Colors.black,
                      ),
                      decoration: InputDecoration(
                        labelText: "First Name",
                        floatingLabelStyle: const TextStyle(
                          color: Color(0xFF1cbb7c),
                          fontWeight: FontWeight.w600,
                        ),
                        labelStyle: TextStyle(
                          color: Colors.grey.shade500,
                          fontWeight: FontWeight.w600,
                        ),
                        enabledBorder: OutlineInputBorder(
                          borderRadius: BorderRadius.circular(10),
                          borderSide: const BorderSide(
                            width: 1,
                            color: Colors.grey,
                          ),
                        ),
                        focusedBorder: OutlineInputBorder(
                          borderRadius: BorderRadius.circular(10),
                          borderSide: const BorderSide(
                            width: 2,
                            color: Color(0xFF1cbb7c),
                          ),
                        ),
                        border: OutlineInputBorder(
                          borderRadius: BorderRadius.circular(10),
                          borderSide: BorderSide.none,
                        ),
                        contentPadding:
                            const EdgeInsets.fromLTRB(20, 15, 20, 15),
                        fillColor: Colors.white,
                        filled: true,
                      ),
                      controller: firstNameController,
                      keyboardType: TextInputType.name,
                      onSaved: (value) {
                        firstNameController.text = value!;
                      },
                      textInputAction: TextInputAction.done,
                    ),
                  ),
                ),
                ElevatedButton(
                  onPressed: () {
                    setState(() {
                      firstName = firstNameController.text;
                      print(firstName);
                    });
                  },
                  child: Text("Save Data"),
                ),
                firstName == null ? Text("") : Text(firstName!),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

Before Putting Text Value -->> enter image description here

After Putting Text Value -->> enter image description here

CodePudding user response:

Why don't you just use a TextEditingController?

just initialise one like this:

TextEditingController yourController = TextEditingController();

and then use it in the textformfield:

controller: yourController;

when the button is clicked, you execute:

String enteredText = yourController.text();
print(enteredText);

CodePudding user response:

class _MyHomePageState extends State<MyHomePage> {
  TextEditingController tc = TextEditingController();
  @override
  Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
    title: Text(widget.title),
  ),
  body: Center(
    child: Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        TextFormField(
          controller: tc,
        ),
        ElevatedButton(
            child: Text("Print"),
            onPressed: () {
              print(tc.text);
              Future.delayed(Duration(seconds: 1), () {
                tc.clear();
              });
            }),
      ],
    ),
  ),
);
}
 }

Now, we are using TextEditingController here because it gives control to the parent widget over its child state. To know more

Now, .text Contains the value entered in the TextField. So, when the button is pressed the value is printed and the form is cleared.

  •  Tags:  
  • Related