# Dart - Form BLoC

Style: Wyatt Analysis SDK: Dart & Flutter

Form Bloc for Dart & Flutter. ## Features - Form * FormInputValidator: - Store data - Validate this data * FormInputMetadata: - Store infos and options about an input. * FormInput: - Associaite a key, to a validator and metadata. * FormData: *collection of inputs* - Contain all inputs - Basic set operation - FormDataCubit * Data management behind a form. - Use entries to pass a FormData object - You can use several pre configured `FormInputValidator` for validation - You can use updateFormData() to change `FormData` during runtime (intersection, union, difference or replace) - Consistent * Every class have same naming convention ## Getting started Simply add `wyatt_form_bloc` in `pubspec.yaml`, then ```dart import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; ``` ## Usage Firstly, you have to create your form inputs. ```dart static List getNormalEntries() { return const [ FormInput(formFieldName, Name.pure()), FormInput(formFieldEmail, Email.pure()), FormInput(formFieldPhone, Phone.pure()), FormInput(formFieldList, ListOption.pure(defaultValue: ['checkbox3'])), FormInput(formFieldRadio, TextString.pure()), FormInput(formFieldPro, Boolean.pure(), metadata: FormInputMetadata(name: 'business')), FormInput(formFieldHidden, Boolean.pure(), metadata: FormInputMetadata(export: false)), ]; } static List getBusinessEntries() { const entries = [ FormInput(formFieldSiren, Siren.pure()), FormInput(formFieldIban, Iban.pure()), ]; return getNormalEntries() + entries; } static FormData getNormalFormData() { return FormData(getNormalEntries()); } static FormData getProFormData() { return FormData(getBusinessEntries()); } ``` > Let's create functions to enable dynamic changes in runtime. > When creating metadata with `FormInputMetadata`, `T` is the type of `extra` object. Then a `FormData` is a collection of inputs. You can `validate`, `contains`, `intersection`, `difference`, `union`, or `clone` this data. After that, you have to extends `FormDataCubit`. ```dart class CustomFormCubit extends FormDataCubit { CustomFormCubit({required FormData inputs}) : super(inputs: inputs); @override Future submitForm() { log(state.data.toMap().toString()); // Handle all your logic here. emit(...) } } ``` > The submited form is in `state.data` ! Don't forget to create and provide it ! ```dart FormDataCubit _formCubit = CustomFormCubit(inputs: getNormalFormData()); return BlocProvider( create: (context) => _formCubit, child: const WidgetTree(), ); ``` You can now create the first form input ! ```dart class _EmailInput extends StatelessWidget { @override Widget build(BuildContext context) { return BlocBuilder( builder: (context, state) { return TextField( onChanged: (email) => context .read() .dataChanged(formFieldEmail, Email.dirty(email)), keyboardType: TextInputType.emailAddress, decoration: InputDecoration( labelText: 'email', helperText: '', errorText: state.data.isNotValid(formFieldEmail) ? 'invalid email' : null, ), ); }, ); } } ``` Then, you can create the trigger ```dart class _SignUpButton extends StatelessWidget { @override Widget build(BuildContext context) { return BlocBuilder( buildWhen: (previous, current) => previous.status != current.status, builder: (context, state) { return state.status.isSubmissionInProgress ? const CircularProgressIndicator() : ElevatedButton( onPressed: state.status.isValidated ? () => context.read().submitForm() : null, child: const Text('SIGN UP'), ); }, ); } } ``` > With `state.status` you can access the status of the form to check if there is an error or if it's in submission.