Angular 14 new Feature — Typed Forms

Mushegh Zakaryan
3 min readJul 27, 2022

Many improvements and bug fixes in the most recent Angular 14 release were directly provided by members of the community, from the addition of router strong typing to more tree-shakable error messages. But let’s focus on a feature that is a personal favorite of mine.

When we make mistakes in our code, TypeScript may catch them. That’s fantastic, but TypeScript also enables us to avoid committing such errors in the first place. This functionality is now accessible for our “Reactive Forms”.

Implementing strict type for the Angular Reactive Forms package was the top GitHub issue for Angular The first publication of this issue was on December 30, 2016, and it was resolved in version 14.

The use of autocomplete with typed forms is demonstrated here. awesome, right?

The values included in form controls, groups, and arrays are type-safe over the full API surface thanks to typed forms. This makes forms safer, especially for complicated instances with deep nesting.

The Angular update guide lists two new types: UntypedFormGroup and UntypedFormControl.
Why do you need this then? If you are still using an outdated version of Angular, the ng update command will replace any form classes with untyped counterparts (FormGroup -> UntypedFormGroup, for instance). Then, at your own speed, you may enable types (for instance, UntypedFormGroup -> FormGroup).

// v13 untyped form
const cat = new FormGroup({
name: new FormGroup(
first: new FormControl('Barb'),
last: new FormControl('Smith'),
),
lives: new FormControl(9)
});

// v14 untyped form after running `ng update`
const cat = new UntypedFormGroup({
name: new UntypedFormGroup(
first: new UntypedFormControl('Barb'),
last: new UntypedFormControl('Smith'),
),
lives: new UntypedFormControl(9)
});

Here, you can see the differences between versions 13 and 14 as well as how things will look following the ng upgrade.

Specifying an Explicit Type

interface LoginForm {
email: FormControl<string>;
password?: FormControl<string>;
}

const login = new FormGroup<LoginForm>({
email: new FormControl('', {nonNullable: true}),
password: new FormControl('', {nonNullable: true}),
});

{nonNullable: true}: Whether to use the initial value used to construct the FormControl as its default value as well. If this option is false or not provided, the default value of a FormControl is null. When a FormControl is reset without an explicit value, its value reverts to its default value.

Here, we type FormGroup with an interface, but you may also add types directly for FormControls.

const email = new FormControl<string | null>(null);

This section applies to you if you use FormBuilder.

The FormBuilder class has been updated to accommodate the new kinds, much like the examples above.

Additionally, if we want to utilize the nonNullable option in every control, we can use the new injectable NonNullableFormBuilder to eliminate boilerplate code:


interface User{
name: FormControl<string>;
age: FormControl<number>;
}
constructor(
private fb: FormBuilder
) {
}
initializeForm(): void{
this.newFormGroup = this.fb.group<User>({
name: this.fb.control('', [Validators.required]),
age: this.fb.control(10, [Validators.required]),
});
}

And finally, You must begin utilizing Reactive Forms since this new functionality only applies to Reactive Forms if for some reason you are using a Template-driven method and wish to use Typed Forms.

For more information: https://angular.io/guide/typed-forms

Best Regards,
Mushegh Zakaryan

https://www.linkedin.com/in/mushegh-zakaryan/

--

--