yN.
yN.

Reputation: 2257

flutter validate radio buttons

How can I add a validator function to a list of RadioButtons in order to have them validated (like TextFormFields with _formKey.currentState.validate()) after the User submits the Form?

Upvotes: 11

Views: 15938

Answers (4)

VISHNU PRABHAKARAN
VISHNU PRABHAKARAN

Reputation: 89

I know this reply is a little late.

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

enum Gender { male, female, other }
class MyApp extends StatefulWidget {
const MyApp({super.key});

@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
  Gender? gender;
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
          key: _formKey,
          child: Center(
            child: FormField(
              validator: (value) {
                if (value == null) {
                  return "Please select a gender";
                }
                return null;
              },
              builder: (FormFieldState<Gender> field) => Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  ListTile(
                    leading: Radio<Gender>(
                      value: Gender.male,
                      groupValue: gender,
                      onChanged: (Gender? selectedValue) {
                        setState(() {
                          gender = selectedValue;
                        });
                      },
                    ),
                    title: Text(Gender.male.name.capitalize()),
                  ),
                  ListTile(
                    leading: Radio<Gender>(
                      value: Gender.female,
                      groupValue: gender,
                      onChanged: (Gender? selectedValue) {
                        setState(() {
                          gender = selectedValue;
                        });
                      },
                    ),
                    title: Text(Gender.female.name.capitalize()),
                  ),
                  ListTile(
                    leading: Radio<Gender>(
                      value: Gender.other,
                      groupValue: gender,
                      onChanged: (Gender? selectedValue) {
                        setState(() {
                          gender = selectedValue;
                        });
                      },
                    ),
                    title: Text(Gender.other.name.capitalize()),
                  ),
                  const SizedBox(height: 20),
                  if (field.errorText != null) Text(field.errorText!),

                  const SizedBox(height: 20),
                  ElevatedButton(
                    onPressed: () {
                      _formKey.currentState?.validate() ?? false;
                    },
                    child: const Text('Submit'),
                  ),
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }
}


// Extension method to capitalize first letter
extension StringCapitalization on String {
  String capitalize() {
    return "${this[0].toUpperCase()}${substring(1)}";
  }
}

Upvotes: 0

Biloliddin Makhmudov
Biloliddin Makhmudov

Reputation: 112

Use FormField(). You can use FormField classes validator, autovalidateMode, and other functions. Here is my sample code

body: Center(
    // Center is a layout widget. It takes a single child and positions it
    // in the middle of the parent.
    child: FormField(
           autovalidateMode: AutoValidateMode.onUserInteraction,     
           validator: (value){
           return optionBool == null ? "Required field" : null;
      },
    builder: (FormFieldState<dynamic> field){
      return MyCustomWidget();
    }
  ),

Upvotes: 0

Big_Chair
Big_Chair

Reputation: 3239

I didn't want to use a whole package just for that, but this article helped me solve it manually: https://medium.com/free-code-camp/how-to-validate-forms-and-user-input-the-easy-way-using-flutter-e301a1531165

It's not complicated, you basically just check if a value is selected:

  // I have multiple forms because I am using a stepper
  // so each step form gets its own validation
  bool _validateForm() {
    switch (currentStep) {
      case 0:
        if (userType == null) {
          showRadioError();
          return false;
        }
        break;

      // ... Other cases / steps

    }

    return true;
  }

  // Validate the whole form of the step on button press of "next" button
  void onStepContinue(int stepAmount) {
    bool isLastStep = (currentStep == stepAmount - 1);
    if (isLastStep) {
      //Do something with this information
      print("FINISHED!");
    } else {
      if (_validateForm()) {
        currentStep += 1;
        notifyListeners();
      }
    }
  }

Upvotes: 0

chunhunghan
chunhunghan

Reputation: 54367

You can copy paste run full code below
You can use package https://pub.dev/packages/flutter_form_builder
It support bulid-in validators such as FormBuilderValidators.required() you can directly use
you can also use custom validator function https://pub.dev/packages/flutter_form_builder#custom-validator-function

FormBuilderRadio(
                      decoration:
                          InputDecoration(labelText: 'My chosen language'),
                      attribute: "best_language",
                      leadingInput: true,
                      onChanged: _onChanged,
                      validators: [FormBuilderValidators.required()],
                      options:
                          ["Dart", "Kotlin", "Java", "Swift", "Objective-C"]
                              .map((lang) => FormBuilderFieldOption(
                                    value: lang,
                                    child: Text('$lang'),
                                  ))
                              .toList(growable: false),
                    ),

working demo

enter image description here

full code

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter FormBuilder Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        inputDecorationTheme: InputDecorationTheme(
          labelStyle: TextStyle(color: Colors.purple),
        ),
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  MyHomePageState createState() {
    return MyHomePageState();
  }
}

class MyHomePageState extends State<MyHomePage> {
  var data;
  bool autoValidate = true;
  bool readOnly = false;
  bool showSegmentedControl = true;
  final GlobalKey<FormBuilderState> _fbKey = GlobalKey<FormBuilderState>();
  final GlobalKey<FormFieldState> _specifyTextFieldKey =
      GlobalKey<FormFieldState>();

  ValueChanged _onChanged = (val) => print(val);
  var genderOptions = ['Male', 'Female', 'Other'];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("FormBuilder Example"),
      ),
      body: Padding(
        padding: EdgeInsets.all(10),
        child: SingleChildScrollView(
          child: Column(
            children: <Widget>[
              FormBuilder(
                // context,
                key: _fbKey,
                autovalidate: true,
                initialValue: {
                  'movie_rating': 5,
                },
                readOnly: false,
                child: Column(
                  children: <Widget>[
                    FormBuilderRadio(
                      decoration:
                          InputDecoration(labelText: 'My chosen language'),
                      attribute: "best_language",
                      leadingInput: true,
                      onChanged: _onChanged,
                      validators: [FormBuilderValidators.required()],
                      options:
                          ["Dart", "Kotlin", "Java", "Swift", "Objective-C"]
                              .map((lang) => FormBuilderFieldOption(
                                    value: lang,
                                    child: Text('$lang'),
                                  ))
                              .toList(growable: false),
                    ),
                  ],
                ),
              ),
              Row(
                children: <Widget>[
                  Expanded(
                    child: MaterialButton(
                      color: Theme.of(context).accentColor,
                      child: Text(
                        "Submit",
                        style: TextStyle(color: Colors.white),
                      ),
                      onPressed: () {
                        if (_fbKey.currentState.saveAndValidate()) {
                          print(_fbKey.currentState.value);
                        } else {
                          print(_fbKey.currentState.value);
                          print("validation failed");
                        }
                      },
                    ),
                  ),
                  SizedBox(
                    width: 20,
                  ),
                  Expanded(
                    child: MaterialButton(
                      color: Theme.of(context).accentColor,
                      child: Text(
                        "Reset",
                        style: TextStyle(color: Colors.white),
                      ),
                      onPressed: () {
                        _fbKey.currentState.reset();
                      },
                    ),
                  ),
                ],
              ),
            ],
          ),
        ),
      ),
    );
  }
}

Upvotes: 7

Related Questions