DEV Community

Preston Lamb
Preston Lamb

Posted on • Originally published at prestonlamb.com on

Angular Typed Reactive Forms

tldr;

Reactive forms in Angular are a convenient way to manage your forms and react to changes made by the user. One issue with them has been that the value of the form has not been typed. Because of this, you could improperly access a value from a form and not know until runtime. Angular v14 introduces typed reactive forms, and removes this potential issue.

The Issue

Let’s look at a sample reactive form declaration:

this.form = new FormGroup({
  name: new FormControl(''),
  email: new FormControl('')
});
Enter fullscreen mode Exit fullscreen mode

This form has two controls, name and email. With untyped reactive forms, I could write the following (valid) code, which would cause an error at runtime:

const firstName = this.form.value.name.firstName;
Enter fullscreen mode Exit fullscreen mode

The name value on the form is just a string, not an object, so I shouldn’t be able to access .firstName. The reason I can in this example is because at some point in the API for reactive forms, any was used in the type.

Strongly typed reactive forms will change this behavior, however, and ensure that you only access the value of the form correctly.

Typed Reactive Forms

Moving forward, creating reactive forms will allow for specifying the type of the value of the form and the controls. For example:

const name = new FormControl('Preston Lamb');
Enter fullscreen mode Exit fullscreen mode

Will create a new FormControl with the automatically inferred type of FormControl<string|null>. It can be null because by default, the reset method on the FormControl will set the value to null.

If you want the value to be non-nullable, you can use the initialValueIsDefault option when creating a FormControl:

const name = new FormControl('Preston Lamb', { initalValueIsDefault: true );
Enter fullscreen mode Exit fullscreen mode

The name control can no longer be set to null; if it’s reset the value will go back to ‘Preston Lamb’ in this case (or whatever the initial value is set to).

You can also explicitly set the type of a form control:

const email = new FormControl<string>('', { initialValueIsDefault: true });
Enter fullscreen mode Exit fullscreen mode

The email control has the same functionality as the above name control, with the exception of the default value being an empty string.

Another option for typing reactive forms is by providing an interface as the type for a FormGroup. Consider the following:

interface User {
  name: string;
  email: string;
}

const userForm = new FormGroup<User>({
  name: new FormControl(''),
  email: new FormControl('')
});
Enter fullscreen mode Exit fullscreen mode

By typing the form like this, we ensure that no controls can be added or removed from the form. All the attributes of the interface that are not optional must be present on the form. Optional attributes of the interface can be added or removed later on.

Conclusion

Having type-safe forms in Angular apps is a good step in the right direction. The possibility of accessing an attribute that doesn’t exist, or setting the value of a control to an unsupported value, is removed if the form and its controls are typed. The developer experience of using reactive forms will be better with these types.

You can start using typed forms as of Angular v14

Top comments (0)