Generate Forms
Generate form widget and link it automatically with screen viewModel depending on reactive_forms package.xflutter_cli generate form
Generated Code:
- CLI generate a isolated Form Widget, so you can re-use it in any implicit screen (mobile, tablet or desktop):
class RegisterForm extends StatelessWidget { const RegisterForm({super.key}); @override Widget build(BuildContext context) { return InstanceBuilder<RegisterViewModel>( builder: (RegisterViewModel viewModel) { final formGroup = viewModel.params.registerForm; return ReactiveForm( formGroup: formGroup, child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ // form fields Column( children: [ // name CustomizedReactiveFormField<String>( formControlName: 'name', labelText: 'name'.tr(), keyboardType: TextInputType.text, textInputAction: TextInputAction.next, onSubmitted: (_) => formGroup.focus('email'), ), const SizedBox(height: formSpacing), // email CustomizedReactiveFormField<String>( formControlName: 'email', labelText: 'email'.tr(), keyboardType: TextInputType.emailAddress, textInputAction: TextInputAction.next, onSubmitted: (_) => formGroup.focus('phone'), ), const SizedBox(height: formSpacing), // phone CustomizedReactivePhoneField( formControlName: 'phone', labelText: 'phone'.tr(), textInputAction: TextInputAction.next, onSubmitted: () => formGroup.focus('password'), ), const SizedBox(height: formSpacing), // password CustomizedReactiveFormField<String>( formControlName: 'password', labelText: 'password'.tr(), keyboardType: TextInputType.text, textInputAction: TextInputAction.next, obscureText: true, onSubmitted: (_) => formGroup.focus('confirm_password'), ), const SizedBox(height: formSpacing), // confirmPassword CustomizedReactiveFormField<String>( formControlName: 'confirm_password', labelText: 'confirm_password'.tr(), keyboardType: TextInputType.text, textInputAction: TextInputAction.done, obscureText: true, onSubmitted: (_) {}, ), const SizedBox(height: formSpacing), ], ), // submit widget Column( children: [ SizedBox( width: double.infinity, child: CustomizedButton( child: Text('next'.tr()), callback: () { if (formGroup.valid) { debugPrint(formGroup.value.toString()); } else { formGroup.markAllAsTouched(); } }, ), ), ], ), ], ), ); }, ); } }
- CLI generate the code in the ViewModel Params if the screen generate with state-management,
otherwise the formGroup will be generated inside the form widget as standalone form to re-use it everywhere:class RegisterParams { final registerForm = FormGroup({ 'name': FormControl<String>( validators: [Validators.required], ), 'email': FormControl<String>( validators: [ Validators.required, Validators.email, ], ), 'phone': FormControl<PhoneNumber>( validators: [ PhoneValidators.validMobile, PhoneValidators.required, ], ), 'password': FormControl<String>( validators: [ Validators.required, Validators.minLength(8), ], ), 'confirm_password': FormControl<String>( validators: [Validators.required], ), }, validators: [ // matching 'password' and 'confirm_password' formControls const MatchingValidator( controlName: 'password', matchingControlName: 'confirm_password', ), ]); }
Result:
- xflutter_cli_modules_application
- android
- assets
- ios
- lib
- modules
- authentication
- presentation
- screens
- register
- mobile
- viewmodels
- widgets
Usage:
Name | Type | Description | Allowed Values | Example |
---|---|---|---|---|
src | option | specify one of the modules to execute command in (monorepo workspace or standalone modular-app) | - | |
path | option | generate form path | - | |
fields | option | declaring generated form-fields directly instead of inserting them one by one by the terminal | text, email, boolean, password, phone_number, number_integer, number_double, confirm_password | name:text,user_mail:email |
source | option | import file from specific module, this is helpful when you have multiple files with same name and one of them should be imported in the generated file, so you need to tell CLI which one should be imported | - | filename.dart:my_app1 |
sources | option | import file from multiple modules, this is helpful when you have multiple files with same name and many of them of them should be imported in the generated file, so you need to tell CLI which files should be imported | - | models.dart:my_package1, models.dart:my_package2 |