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('')
});
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;
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');
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 );
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 });
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('')
});
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)