Why use Reactive Forms in Flutter?
Tags: flutter, forms, validations, reactive
Published: 2020-07-20 18:14:59

### Haven't you ever felt that getting data from a Form, validating a field, or even disabling the submit button is tedious and full of boilerplate code?

Fortunately, that's why **[Reactive Forms](https://pub.dev/packages/reactive_forms)** exists.

### 1. Ease and clean way of collecting data from your Forms.

No more *onSave*, *onChanges*, *onEditionCompleted* callbacks needed or *TextEditionControllers* to collect data from inputs

**Reactive Forms** get a clean separation between views and model and maintains data synchronization in a transparent two-way binding mechanism. Just declare your model and define your widgets. Then lay back and relax, data will flow smoothly.

```dart
// group and controls
final form = FormGroup({
  'name': FormControl<String>(value: 'John Doe'),
  'email': FormControl<String>(),
});
```

````dart
// two-way bindings with widgets
@override
Widget build(BuildContext context) {
  return ReactiveForm(
    formGroup: this.form,
    child: Column(
      children: <Widget>[
        ReactiveTextField(
          formControlName: 'name',
        ),
        ReactiveTextField(
          formControlName: 'email',
        ),
      ],
    ),
  );
}
```

### 2. Transparent Validations of inputs fields.

No more StatefulWidget defining a *key* for the *Form* widget, goodbye to *Form.of(context)* and Goodbye to:
```dart
// boilerplate code...
if (form.validate()) {
  form.save();
} else {
  setState(() {
    _autoValidate = true;
  });
}
```

**Reactive Forms** Validations occurs transparently. Just declare your model and define the **validators** you need. It will also handle validity of the entire Form and will shows error messages when needed. All of that without you needing to write a single line of imperative code.

```dart
// controls and validators
final form = FormGroup({
  'email': FormControl<String>(validators: [
    Validators.required,
    Validators.email,
  ]),
});
```

````dart
// customize validation messages
@override
Widget build(BuildContext context) {
  return ReactiveForm(
    formGroup: this.form,
    child: Column(
      children: <Widget>[
        ReactiveTextField(
          formControlName: 'email',
          validationMessages: (control) => {
            ValidationMessage.required: 'The email must not be empty',
            ValidationMessage.email: 'The email value must be a valid email'
          },
        ),
      ],
    ),
  );
}
```

### 3. Enable/Disable buttons depending of Form validity.

Getting this behavior, even in such a great framework as Flutter, can sometimes be hard and full of boilerplate code.

In **Reactive Forms** is as simple as asking to the Form if it is valid or not:

```dart
@override
  Widget build(BuildContext context) {
    final form = ReactiveForm.of(context);
    return RaisedButton(
      child: Text('Submit'),
      // just ask to the form
      onPressed: form.valid ? _onPressed : null,
    );
  }
```

### 4. Perfect integration with [Provider](https://pub.dev/packages/provider) plugin and other state management plugins.

The use of a state management library (MVC, MVVM or just BLoc) cleans your code and perfectly separates responsibilities between the UI and business logic.

````dart
// your bloc/controller/viewmodel/etc
class SignInViewModel {
  final form = FormGroup({
    'email': FormControl<String>(validators: [Validators.required, Validators.email]),
    'password': FormControl<String>(validators: [Validators.required, Validators.minLength(8)])
  });

  void signIn() {
    final credentials = this.form.value;
    // ... make some business logic
    // ...
  }

}
```

```dart
// simple sign-in view
class SignInScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final viewModel = Provider.of<SignInViewModel>(context, listen: false);
    return ReactiveForm(
      formGroup: viewModel.form,
      child: Column(
        children: <Widget>[
          ReactiveTextField(
            formControlName: 'email',
          ),
          ReactiveTextField(
            formControlName: 'password',
            obscureText: true,
          ),
          ReactiveFormConsumer(
            builder: (context, form, child) {
              return RaisedButton(
                child: Text('Submit'),
                // if form valid, sign-in
                onPressed: form.valid ? viewModel.signIn : null,
              );
            },
          ),
        ],
      ),
    );
  }
}
```

### 5. Focus/Unfocus text fields.

To add or remove focus to a control use FormControl.focus() or FormControl.unfocus(). No more *StatefulWidgets* and FocusNode declarations:

```dart
// declare a form and controls
final form = FormGroup({
  'name': FormControl<String>(value: 'John Doe'),
});

// the name control
final name = form.control('name');

// UI text field get focus and the device keyboard pop up
name.focus();

// UI text field lose focus
name.unfocus();
```

## What is Reactive Forms?  

- **Reactive Forms** provides a model-driven approach to handling form inputs whose values change over time. It's heavily inspired in [Angular Reactive Form](https://angular.io/guide/reactive-forms).

- It lets you focus on business logic and save you time from collect, validate and maintain synchronization data between models and widgets.

- Remove boilerplate code and brings you the possibility to write clean code with minimal effort.

- Integrates perfectly with common state management libraries like Provider, Bloc, and many others.

## What is not Reactive Forms?

- **Reactive Forms** is not a fancy widgets package. It's not a widget's library with new shapes, colors, or animations. It frees you from the responsibility of gathering and validating the data. And keeps the data in sync between your model and your widgets.

- **Reactive Forms** does not replace native widgets that you commonly use in Flutter like *TextFormField*, *DropdownButtonFormField* or *CheckboxListTile*. It brings new two-way binding capabilities and much more features to those same widgets.

**Reactive Forms** is much more. This POST was just a preview of some basic features. Please visit [Github Repo](https://github.com/joanpablo/reactive_forms) or plugin page in [puv.dev](https://pub.dev/packages/reactive_forms) for full documentation.