Home > Software engineering >  Why does the Flutter DatePicker update my form values but not my UI?
Why does the Flutter DatePicker update my form values but not my UI?

Time:01-22

There were similar questions but their circumstances and solutions did not apply to my situation. All of my other inputs in the form work fine, but I've been banging my head against the wall for two weeks trying to figure this out.

Excuse the hacky code, we're migrating auth services and I had to find a way to handle multiple structures for the same data and detect which login method was used, but that's a tangent.

Anyway, here's my code. I'm relatively new at Flutter development so please tell me if I did something dumb.


import 'package:clash_of_the_pencils/widgets/body_text.dart';
import 'package:clash_of_the_pencils/widgets/box_container.dart';
import 'package:clash_of_the_pencils/widgets/general_button.dart';
import 'package:clash_of_the_pencils/widgets/heading_text.dart';
import 'package:clash_of_the_pencils/widgets/input_field.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:clash_of_the_pencils/models/auth_model.dart';
import 'package:go_router/go_router.dart';
import 'package:provider/provider.dart';

class RegistrationForm extends StatefulWidget {
  const RegistrationForm({super.key});

  @override
  State<RegistrationForm> createState() => RegistrationFormState();
}

class RegistrationFormState extends State<RegistrationForm> {
  String errorMessage = "";
  String successMessage = "";
  bool _pwObscure = true;
  String firstName = "";
  String lastName = "";
  String codename = "";
  String email = "";
  String _password = "";
  String codenameStr = "https://app.xxxxxxxxxxxxxxx.com/codename";
  String dob = "";

  @override
  Widget build(BuildContext context) {
    final user = context.watch<AuthModel>().user;
    return MultiProvider(
        providers: [
          ChangeNotifierProvider(create: (_) => AuthModel()),
        ],
        child: Container(
          width: double.infinity,
          padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 20),
          child: Center(
            child: SingleChildScrollView(
              child: Form(
                  child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                    //* Top Heading and test
                    TextHeadings(
                      title: user['name'] != null
                          ? "Just a few more details"
                          : "Registration",
                      textSize: 45,
                    ),

                    const SizedBox(height: 10),

                    //* Box with the form
                    CustomBoxContainer(
                        boxContent: Center(
                            child: Column(children: [
                      //* Form Description
                      BodyText(
                        title: user['name'] != null
                            ? "Complete the form below to finish registration"
                            : "Complete the form to create an account",
                        textSize: 18,
                        textColor: Colors.white,
                        textAlign: TextAlign.center,
                        fontWeight: FontWeight.bold,
                      ),

                      const SizedBox(height: 25),

                      //* Error message
                      Container(
                        child: errorMessage != ""
                            ? (Column(
                                children: [
                                  CustomBoxContainer(
                                    backgroundColor: const Color(0xffef5f5f),
                                    borderColor: const Color(0xffef2828),
                                    boxContent: BodyText(
                                      title: errorMessage,
                                      textAlign: TextAlign.center,
                                      fontWeight: FontWeight.bold,
                                      textColor: Colors.white,
                                    ),
                                  ),
                                  const SizedBox(height: 25),
                                ],
                              ))
                            : null,
                      ),

                      //* Success message
                      Container(
                        child: successMessage != ""
                            ? (Column(
                                children: [
                                  CustomBoxContainer(
                                    backgroundColor: const Color(0xff79b441),
                                    borderColor: const Color(0xff17974e),
                                    boxContent: BodyText(
                                      title: successMessage,
                                      textAlign: TextAlign.center,
                                      fontWeight: FontWeight.bold,
                                      textColor: Colors.white,
                                    ),
                                  ),
                                  const SizedBox(height: 25),
                                ],
                              ))
                            : null,
                      ),

                      //* Codename Field
                      InputField(
                          child: TextFormField(
                        initialValue:
                            user[codenameStr] ?? user['nickname'] ?? codename,
                        decoration: const InputDecoration(
                          border: InputBorder.none,
                          labelText: "Codename",
                          hintText: "Choose a cool codename",
                        ),
                        onChanged: (value) => setState(() {
                          codename = value;
                        }),
                      )),

                      const SizedBox(height: 10),

                      //* First Name Field
                      user['given_name'] == null
                          ? InputField(
                              child: TextFormField(
                                decoration: const InputDecoration(
                                  border: InputBorder.none,
                                  hintText: "What's your first name?",
                                  labelText: "First Name",
                                ),
                                onChanged: (value) => {
                                  setState(() {
                                    firstName = value;
                                  }),
                                },
                                initialValue: firstName.isNotEmpty
                                    ? firstName
                                    : user['given_name'] ?? "",
                              ),
                            )
                          : const SizedBox(
                              height: 0,
                            ),

                      const SizedBox(height: 10),

                      //* Last Name Field
                      user['family_name'] == null
                          ? InputField(
                              child: TextFormField(
                                  decoration: const InputDecoration(
                                    border: InputBorder.none,
                                    hintText: "What's your last name?",
                                    labelText: "Last Name",
                                  ),
                                  onChanged: (value) => {
                                        setState(() {
                                          lastName = value;
                                        }),
                                      },
                                  initialValue: lastName.isNotEmpty
                                      ? lastName
                                      : user['family_name'] ?? ''))
                          : const SizedBox(height: 0),

                      SizedBox(height: user['family_name'] == null ? 10 : 0),

                      //* Email Field
                      user['email'] == null
                          ? InputField(
                              child: TextFormField(
                              decoration: const InputDecoration(
                                border: InputBorder.none,
                                hintText: "[email protected]",
                                labelText: "Email",
                              ),
                              initialValue: email.isNotEmpty
                                  ? email
                                  : user['email'] ?? '',
                            ))
                          : const SizedBox(height: 0),

                      SizedBox(height: user['email'] == null ? 10 : 0),

                      //* DOB Field
                      InputField(
                          child: TextFormField(
                        readOnly: true,
                        decoration: InputDecoration(
                          border: InputBorder.none,
                          labelText: 'Date of Birth',
                          suffixIcon: IconButton(
                            icon: const Icon(Icons.edit),
                            onPressed: () => showDatePicker(
                                    initialDatePickerMode: DatePickerMode.year,
                                    context: context,
                                    initialDate: DateTime.now().subtract(
                                        const Duration(days: 365 * 13)),
                                    firstDate: DateTime(1900),
                                    lastDate: DateTime.now().subtract(
                                        const Duration(days: 365 * 13)))
                                .then(
                              (value) => {
                                setState(() {
                                  dob =
                                      '${value!.month.toString()}/${value.day.toString()}/${value.year.toString()}';
                                })
                              },
                            ),
                          ),
                        ),
                        initialValue: dob,
                      )),
                      const SizedBox(height: 10),
                      // Password field
                      InputField(
                        child: TextFormField(
                          decoration: InputDecoration(
                              border: InputBorder.none,
                              labelText: 'Password',
                              suffixIcon: IconButton(
                                icon: Icon(_pwObscure
                                    ? Icons.visibility_off
                                    : Icons.visibility),
                                onPressed: () {
                                  setState(() {
                                    _pwObscure = !_pwObscure;
                                  });
                                },
                              )),
                          initialValue: _password.isNotEmpty ? _password : "",
                          obscureText: _pwObscure,
                          enableSuggestions: false,
                          onChanged: (value) => {
                            setState(() => {
                                  if (!_pwObscure) _pwObscure = true,
                                  _password = value,
                                }),
                            setState(() {
                              _pwObscure = true;
                            })
                          },
                        ),
                      ),

                      const SizedBox(height: 15),

                      //* Submit BTN
                      GeneralButton(
                        onPressed: () async {
                          // ignore: todo
                          // TODO: Write validation functions
                          Map<String, dynamic> userMetaData = {
                            'codename': codename.isNotEmpty
                                ? codename
                                : user['nickname'],
                            'password': _password.isNotEmpty
                                ? _password
                                : user['password'],
                            'dob': dob,
                          };
                          context
                              .read<AuthModel>()
                              .updateAuth0User({"user_metadata": userMetaData});
                          if (kDebugMode) {
                            print("***** Form Values Submitted");
                          }
                        },
                        buttonText: "Register",
                      ),

                      const SizedBox(height: 15),

                      //* Separator
                      user['name'] == null
                          ? const BodyText(
                              title: "- OR -",
                              textColor: Colors.white,
                            )
                          : const SizedBox(height: 0),

                      SizedBox(height: user['name'] == null ? 15 : 0),

                      //* Auth0 button
                      user['name'] == null
                          ? GeneralButton(
                              onPressed: () {
                                Provider.of<AuthModel>(context, listen: false)
                                    .login(true);
                              },
                              buttonText: "Register using auth0",
                              bgColor: Colors.white,
                              textColor: const Color(0xffFF7F34),
                              borderColor: const Color(0xffFF7F34),
                            )
                          : const SizedBox(height: 0),
                    ]))),

                    user['name'] == null
                        ? const SizedBox(height: 15)
                        : const SizedBox(height: 0),

                    //* Text for registering
                    user['name'] == null
                        ? Row(
                            mainAxisAlignment: MainAxisAlignment.center,
                            children: [
                              const BodyText(
                                title: "Already a member? ",
                                fontWeight: FontWeight.bold,
                                textColor: Colors.white,
                                textSize: 18,
                              ),
                              GestureDetector(
                                onTap: () {
                                  context.push('/login');
                                },
                                child: const BodyText(
                                    title: "SIGN IN!",
                                    fontWeight: FontWeight.bold,
                                    textColor: Color(0xffFF7F34),
                                    textSize: 18),
                              )
                            ],
                          )
                        : const SizedBox(height: 0),
                  ])),
            ),
          ),
        ));
  }

  @override
  void dispose() {
    super.dispose();
  }
}

I picked a date from the DatePicker. I was expecting the UI to show the date that I picked. It did not. My formvalues updated but the new value doesn't show as it does with all of the other inputs.

CodePudding user response:

You have to control with TextEditingController to setState. Instead of using initalValue to setState, you need to use controller.

TextFormField(
    readOnly: true,
    decoration: InputDecoration(
      border: InputBorder.none,
      labelText: 'Date of Birth',
      suffixIcon: IconButton(
        icon: const Icon(Icons.edit),
        onPressed: () => showDatePicker(
                initialDatePickerMode: DatePickerMode.year,
                context: context,
                initialDate:
                    DateTime.now().subtract(const Duration(days: 365 * 13)),
                firstDate: DateTime(1900),
                lastDate:
                    DateTime.now().subtract(const Duration(days: 365 * 13)))
            .then(
          (value) => {
            setState(() {
              dob =
                  '${value!.month.toString()}/${value.day.toString()}/${value.year.toString()}';
            })
          },
        ),
      ),
    ),
    controller: TextEditingController(text: dob), //here is answer
  ),    
  • Related