Tips and Tricks of working with Angular Typed Forms (Part 1)

Tips and Tricks of working with Angular Typed Forms (Part 1)

In this article, we explore typed Forms introduced in Angular 14.

01/30/2023

Web, Angular

What are typed forms?

Typed forms refers to using Typescript interfaces or classes to define the sahpe of the form data instead of using the more relaxed "any" type. This helps with catching errors at compile time, rather than at runtime. To create a strictly typed form in Angular, you can use the FormGroup and FormControl classes, along with interfaces or classes to define the shape of the form data. Unlike, the earlier versions of Angular forms which were not type safe - evaluating to the 'any' type.

Lets review a few tips and tricks of working with Typed forms

FormControl

This Represents a single form input element, like a textbox or checkbox. With typed forms, Angular introduced the nonNullable property which indicates that the formfield cannot be null, empty or undefined.

// Here we are declaring a new formcontrol called location
const location = new FormControl("", { nonNullable: true });
// Will always return a string
const locationValue = location;
// Incase of the form is reset, It will return an empty string instead of null
location.reset();

FormGroup

A collection of FormControls, can be used to represent a group of form elements.

When building large forms, It can be quite taxing to add the nonNullable property on each formField, marking the fields as nonNullable.

A simpler way of creating a NonNullable form would be to use the NonNullableFormBuilder service, instead of FormBuilder.

Here's an example:

// First Example => Using the FormBuilderClass
const fb = new FormBuilder();
const loginForm = fb.nonNullable.group({
   username:  '',
   password: '',
});

// Second Example => Using the injector method
export class AppComponent  {
 loginForm: FormGroup

 constructor(private fb: NonNullableFormBuilder) {
   this.loginForm = fb.group({
     username: ['', [Validators.required]],
     password: ['', [Validators.required, Validators.minLength(8)]],
   });
 }
}

// typed as <string | undefined> (Incase the control is disabled)
loginForm.value.username

// typed as <string | undefined> (Incase the control is disbaled)
loginForm.value.password

On the second example when we try to access the login values we can either get a string or undefined. The undefined is added only if the control is disabled because it will not be included in the value object. We can bypass it using the getRawValue() method:

// typed as <string>
loginForm.getRawValue().username;

// typed as <string>
loginForm.getRawValue().password;

Lastly,Its possible to have controls in a FormGroup that can be added and removed at runtime - This can be represented by optional fields.

interface user {
  name: FormControl<string>;
  age?: FormControl<string>;
}

const form =
  new FormGroup() <
  user >
  {
    user: new FormControl("", { nonNullable: true }),
  };

// Throws an error, since this is required
form.removeControl("name");

// Not a required field, compiles successfully
form.removeControl("age");

Happy Coding!

Author : Joy Linda Wawira

Return to home page