form_extensions 1.0.0 copy "form_extensions: ^1.0.0" to clipboard
form_extensions: ^1.0.0 copied to clipboard

Add .onSaved and .validator to any widget! Make Form() easier!

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:form_extensions/form_extensions.dart';
import 'model/user_model.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(title: 'Flutter Demo', theme: ThemeData(colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), useMaterial3: true), home: const MyHomePage(title: 'Flutter Demo Home Page'));
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final _formKey = GlobalKey<FormState>();

  UserModel userModel = UserModel();

  TextEditingController textFormField = TextEditingController();
  int gender = -1;
  int selectedAge = -1;
  List<String> address = [];
  bool withoutValidator = false;
  bool checkTerm = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(backgroundColor: Theme.of(context).colorScheme.inversePrimary, title: Text(widget.title)),
      body: SingleChildScrollView(
        child: Form(
          key: _formKey,
          child: Column(
            children: [
              //^ TextFormField
              //^ No changes... continue using the same properties.
              Padding(
                padding: const EdgeInsets.all(8.0),
                child: TextFormField(
                  controller: textFormField,
                  decoration: const InputDecoration(hintText: "Name"),
                  onSaved: (value) {
                    userModel.name = value;
                  },
                  validator: (value) {
                    return value == null || value.isEmpty ? 'Required' : null;
                  },
                ),
              ),

              //^ Radio
              const Align(alignment: Alignment.centerLeft, child: Padding(padding: EdgeInsets.symmetric(horizontal: 25, vertical: 10), child: Text("Gender", style: TextStyle(fontWeight: FontWeight.bold)))),
              Column(
                    children: <Widget>[
                      RadioListTile.adaptive(
                        title: const Text("Male"),
                        value: 0,
                        groupValue: gender,
                        onChanged: (int? value) {
                          setState(() {
                            gender = value!;
                          });
                        },
                      ),
                      RadioListTile.adaptive(
                        title: const Text("Female"),
                        value: 1,
                        groupValue: gender,
                        onChanged: (int? value) {
                          setState(() {
                            gender = value!;
                          });
                        },
                      ),
                    ],
                  )
                  .onSaved(() {
                    userModel.gender = gender;
                  })
                  .validator(() {
                    return gender == -1 ? 'You need to select a gender' : null;
                  }),

              //^ Chips
              const Align(alignment: Alignment.centerLeft, child: Padding(padding: EdgeInsets.symmetric(horizontal: 25, vertical: 10), child: Text("Age", style: TextStyle(fontWeight: FontWeight.bold)))),
              Padding(
                padding: const EdgeInsets.symmetric(horizontal: 10),
                child: Row(
                      children: [
                        ChoiceChip(
                          label: const Text('10-20'),
                          selected: selectedAge == 0,
                          onSelected: (bool selected) {
                            setState(() {
                              selectedAge = selected ? 0 : -1;
                            });
                          },
                        ),
                        const SizedBox(width: 10),
                        ChoiceChip(
                          label: const Text('21-30'),
                          selected: selectedAge == 1,
                          onSelected: (bool selected) {
                            setState(() {
                              selectedAge = selected ? 1 : -1;
                            });
                          },
                        ),
                        const SizedBox(width: 10),
                        ChoiceChip(
                          label: const Text('31-40'),
                          selected: selectedAge == 2,
                          onSelected: (bool selected) {
                            setState(() {
                              selectedAge = selected ? 2 : -1;
                            });
                          },
                        ),
                        const SizedBox(width: 10),
                        ChoiceChip(
                          label: const Text('41-50'),
                          selected: selectedAge == 3,
                          onSelected: (bool selected) {
                            setState(() {
                              selectedAge = selected ? 3 : -1;
                            });
                          },
                        ),
                      ],
                    )
                    .onSaved(() {
                      userModel.age = selectedAge;
                    })
                    .validator(() {
                      return selectedAge == -1 ? 'You need to select an age' : null;
                    }),
              ),

              //^ CheckboxListTile
              CheckboxListTile.adaptive(
                title: const Text('Option without validator'),
                value: withoutValidator,
                onChanged: (bool? value) {
                  setState(() {
                    withoutValidator = value!;
                  });
                },
                controlAffinity: ListTileControlAffinity.leading,
              ).onSaved(() {
                userModel.withoutValidator = withoutValidator;
              }),

              //^ ListView
              const Align(alignment: Alignment.centerLeft, child: Padding(padding: EdgeInsets.symmetric(horizontal: 25, vertical: 10), child: Text("Address", style: TextStyle(fontWeight: FontWeight.bold)))),
              ListView.builder(
                    padding: EdgeInsets.zero,
                    shrinkWrap: true,
                    physics: const NeverScrollableScrollPhysics(),
                    itemCount: address.length,
                    itemBuilder: (context, index) {
                      return Padding(
                        padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 5),
                        child: Card(
                          elevation: 0,
                          child: Padding(
                            padding: const EdgeInsets.all(1.0),
                            child: ListTile(
                              title: Text(address[index], maxLines: 1, overflow: TextOverflow.ellipsis),
                              trailing: const Icon(Icons.remove_circle_outline, color: Colors.red),
                              onTap: () {
                                setState(() {
                                  address.removeAt(index);
                                });
                              },
                            ),
                          ),
                        ),
                      );
                    },
                  )
                  .onSaved(() {
                    userModel.address = [];
                    userModel.address!.addAll(address);
                  })
                  .validator(() {
                    return address.isEmpty ? 'You must provide an address' : null;
                  }),
              TextButton.icon(
                onPressed: () {
                  setState(() {
                    address.add("Test address");
                  });
                },
                label: const Text("Add address"),
                icon: const Icon(Icons.add),
              ),

              //^ CheckboxListTile
              CheckboxListTile.adaptive(
                    title: const Text('Terms of use'),
                    value: checkTerm,
                    onChanged: (bool? value) {
                      setState(() {
                        checkTerm = value!;
                      });
                    },
                    secondary: const Icon(Icons.hourglass_empty),
                  )
                  .onSaved(() {
                    userModel.checkTerm = checkTerm;
                  })
                  .validator(() {
                    return !checkTerm ? 'You must accept the terms' : null;
                  }),
            ],
          ),
        ),
      ),
      floatingActionButton: FloatingActionButton.extended(
        backgroundColor: Colors.green,
        onPressed: () {
          ScaffoldMessenger.of(context).hideCurrentSnackBar();

          if (!_formKey.currentState!.validate()) {
            ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('Check the required fields!'), backgroundColor: Colors.red));
          } else {
            _formKey.currentState!.save();

            showDialog(
              context: context,
              builder: (BuildContext context) {
                return AlertDialog(
                  title: const Text('userModel'),
                  content: Text('${userModel.toJson()}'),
                  actions: [
                    TextButton(
                      onPressed: () {
                        Navigator.of(context).pop();
                        ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('Saved!'), backgroundColor: Colors.green));
                      },
                      child: const Text('Close'),
                    ),
                  ],
                );
              },
            );
          }
        },
        label: const Text("Save", style: TextStyle(color: Colors.white)),
        icon: const Icon(Icons.save, color: Colors.white),
      ),
    );
  }
}
3
likes
140
points
35
downloads

Publisher

unverified uploader

Weekly Downloads

Add .onSaved and .validator to any widget! Make Form() easier!

Repository (GitHub)
View/report issues

Topics

#flutter #form #extension #extensions #form-extensions

Documentation

API reference

License

MIT (license)

Dependencies

flutter

More

Packages that depend on form_extensions