Home > OS >  I am unable to do form validation for separate widgets, how to do form validation for divided widget
I am unable to do form validation for separate widgets, how to do form validation for divided widget

Time:11-19

I have separated form widgets into separate files And now I am trying to validate form but not working

When I combined all widgets into 1, form validation working

How to do form validation for separate widgets

these are the following code I have done in separate files

class _OnBoardFormState extends State<OnBoardForm> {
final _formKey = GlobalKey<FormState>();


@override
Widget build(BuildContext context) {
return Container(
  padding: const EdgeInsets.only(left: 16, right: 16),
  child: Form(
    key: _formKey,
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: const [
        //Selection dropdown for first and Last Name

        OnBoardFormName(),
        SizedBox(height: 15),

        //Selection dropdown for Email

        OnBoardFormEmailField(),
        SizedBox(height: 15),

        //Selection dropdown for Gender

        OnBoardFormGenderField(),
        SizedBox(height: 15),

        //Selection dropdown for Age

        OnBoardAgeSelector(),
        SizedBox(height: 15),

        //Selection dropdown for Hight

        OnBoardHeightSelector(),
        SizedBox(height: 15),

        //Selection dropdown for Kgs and Lbs

        OnBoardWeightSelector(),
        SizedBox(height: 15),

        //Selection dropdown for Location

        OnBoardFormLocation(),
        SizedBox(height: 40),

        //Button to submit the form
        //Continue button for next page

        OnBoardFormButton(),
          ],
         ),
       ),
    );
   }
  }

And these are the separate widgets

 class _OnBoardAgeSelectorState extends State<OnBoardAgeSelector> {
  final _formKey = GlobalKey<FormState>();

  // age declarations
  var _selectedIndexForAge = "Age";
  var age = [];

  @override
  void initState() {
    super.initState();
    for (int i = 18; i <= 120; i  ) {
      age.add(i);
    }
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        const Text(
          'AGE',
          style: TextConstants.feildHeadText,
        ),
        const SizedBox(
          height: 2,
        ),
        SizedBox(
          height: 51,
          child: OutlineButton(
            
            shape: const StadiumBorder(),
            padding: const EdgeInsets.only(left: 20, right: 10),
            highlightedBorderColor: Colors.grey,
            borderSide: BorderSide(
              color: Colors.grey.shade500,
              width: 1,
            ),
            onPressed: () {
              // if (_formKey.currentState!.validate()) {
              //   const Text(
              //     "Please select Age",
              //     style: TextStyle(
              //       color: Colors.red,
              //       fontSize: 16,
              //     ),
              //   );
              // }
              showModalBottomSheet(
                context: context,
                builder: (BuildContext context) {
                  return SizedBox(
                    height: 200,
                    child: CupertinoPicker(
                      itemExtent: 32,
                      onSelectedItemChanged: (int index) {
                        setState(
                          () {
                            _selectedIndexForAge = age[index].toString();
                          },
                        );
                      },
                      children: List<Widget>.generate(
                        age.length,
                        (int index) {
                          return Center(
                            child: Text(age[index].toString()),
                          );
                        },
                      ),
                    ),
                  );
                },
              );
            },
            child: Stack(
              children: [
                Align(
                  alignment: Alignment.centerRight,
                  child: SvgPicture.asset('assets/icons/dropdown.svg'),
                ),
                Align(
                  alignment: Alignment.centerLeft,
                  child: Text(
                    _selectedIndexForAge.toString(),
                    textAlign: TextAlign.right,
                    style: TextConstants.fieldPlaceholderText,
                  ),
                ),
              ],
            ),
          ),
        ),
      ],
    );
    }
  }

and so on and other widgets

when i am trying to validate it shows error like this

enter image description here

CodePudding user response:

You need to add a button inside the form to check the validation.

You need to wrap them in scaffold first

You can use _formKey.currentState!.validate()

To validate all the saperate widgets which are defined in saperate files like "Textformfield" and all...

But all the saperate widgets should come under the form widget and have a for key.

Code (Your updated code)

import 'package:flutter/material.dart';
import 'package:stackexample/onbordname.dart';

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

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

class _OnBoardFormState extends State<OnBoardForm> {
  final _formKey = GlobalKey<FormState>();
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        padding: const EdgeInsets.only(left: 16, right: 16),
        child: Form(
          key: _formKey,
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.center,
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              //Selection dropdown for first and Last Name

              OnBoardFormName(),
              SizedBox(height: 15),

              //Selection dropdown for Email
              OnBoardFormName(),
              // OnBoardFormEmailField(),
              SizedBox(height: 15),

              //Selection dropdown for Gender
              OnBoardFormName(),
              // OnBoardFormGenderField(),
              SizedBox(height: 15),

              //Selection dropdown for Age

              // OnBoardAgeSelector(),
              SizedBox(height: 15),

              //Selection dropdown for Hight

              // OnBoardHeightSelector(),
              SizedBox(height: 15),

              //Selection dropdown for Kgs and Lbs

              // OnBoardWeightSelector(),
              SizedBox(height: 15),

              //Selection dropdown for Location

              // OnBoardFormLocation(),
              SizedBox(height: 40),
              Padding(
                padding: EdgeInsets.symmetric(vertical: 16.0),
                child: ElevatedButton(
                  onPressed: () {
                    if (_formKey.currentState!.validate()) {
                      ScaffoldMessenger.of(context).showSnackBar(
                        const SnackBar(content: Text('Good to go...')),
                      );
                    }
                  },
                  child: const Text('Submit'),
                ),
              ),

              //Button to submit the form
              //Continue button for next page

              // OnBoardFormButton(),
            ],
          ),
        ),
      ),
    );
  }
}

TextField

import 'package:flutter/material.dart';

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

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

class _OnBoardFormNameState extends State<OnBoardFormName> {
  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        const Text(
          'FIRST NAME',
          // style: TextConstants.feildHeadText,
        ),
        const SizedBox(
          height: 2,
        ),
        TextFormField(
          // style: TextConstants.fieldPlaceholderText,
          maxLength: 30,
          textCapitalization: TextCapitalization.words,
          autofocus: false,
          decoration: const InputDecoration(
            counterText: "",
            contentPadding: EdgeInsets.only(left: 20.0, right: 10.0),
            border: OutlineInputBorder(
              borderSide: BorderSide(
                color: Color(0xffE3E5F6),
                width: 1,
              ),
              borderRadius: BorderRadius.all(Radius.circular(40)),
            ),
            hintText: 'First Name',
          ),
          validator: (value) {
            if (value == null || value.isEmpty) {
              return 'Please enter first name';
            }
            return value.length < 3
                ? 'Name must be at least 3 to 30 characters long'
                : null;
          },
        ),
      ],
    );
  }
}

Output

Validation working when charecter less than 3

enter image description here

Validation true

enter image description here

Update

You can't put the button in a new file, Because you can't access the state of that form key

If you strictly want to put the button on other file you need to pass the form key to the new screen ( or file ). or use a state management library like ' Bloc or Provider '

But for now i prefer to put the button on the same file.

Thank you

CodePudding user response:

final form = _formKey.currentState;
if (form.validate()){
   form.save();
}

This should be inside Form, form should have _formkey, furthermore you can use autovalidation mode. I think problem is your form.validate() is not inside Form.

  • Related