How to Create Typed Forms in Angular

Oleh Teslenko
Bits and Pieces
Published in
4 min readApr 23, 2023

--

Photo by Mediamodifier on Unsplash

In this article, I want to show you how to create typed forms in Angular.

Although it’s possible to create forms without types, it’s not the best choice when building something great.

Using types in your Angular forms can help catch errors early in the development process, improve code readability and maintainability, and enhance the overall developer experience.

Let’s get started.

First of all, we need to create a simple form using FormGroup:

// typescript file

public userForm: FormGroup;

this.userForm = new FormGroup<any>({
id: 0,
name: 'John',
email: 'test@email.com',
password: '123456',
createdAt: new Date()
});
// html file

<form [formGroup]="userForm">

<div class="form-group">
<label for="name">Name</label>
<input type="text" class="form-control" id="name" formControlName="name">
</div>

<div class="form-group">
<label for="email">Email</label>
<input type="email" class="form-control" id="email" formControlName="email">
</div>

<div class="form-group">
<label for="password">Password</label>
<input type="password" class="form-control" id="password" formControlName="password">
</div>
<button type="submit" class="btn btn-primary" [disabled]="!userForm.valid">Submit</button>

</form>

As you can see, the type of the form is ‘any’. If we want to add types, we should create an interface:

interface IUserForm {
id: FormControl<number | null>;
name: FormControl<string | null>;
email: FormControl<string | null>;
password: FormControl<string | null>;
createdAt: FormControl<Date | null>;
}

In this example, we’ve created an interface with FormControl and a special type in <...>.

Next, we add new FormControl() to our FormGroup:

this.userForm = new FormGroup<IUserForm>({
id: new FormControl<number>(0),
name: new FormControl<string>('John'),
email: new FormControl<string>('test@email.com'),
password: new FormControl<string>('123456'),
createdAt: new FormControl<Date>(new Date())
});

Finally, we add our interface to the userForm variable, and that's all you need to get a typed form.

public userForm: FormGroup<IUserForm>;
// FINAL RESULT
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import {FormControl, FormGroup, ReactiveFormsModule} from "@angular/forms";

interface IUserForm {
id: FormControl<number | null>;
name: FormControl<string | null>;
email: FormControl<string | null>;
password: FormControl<string | null>;
createdAt: FormControl<Date | null>;
}

@Component({
selector: 'app-typed-form-group',
standalone: true,
imports: [CommonModule, ReactiveFormsModule],
templateUrl: './typed-form-group.component.html',
styleUrls: ['./typed-form-group.component.scss']
})
export class TypedFormGroupComponent {
public userForm: FormGroup<IUserForm>;

constructor() {
this.userForm = new FormGroup<IUserForm>({
id: new FormControl<number>(0),
name: new FormControl<string>('John'),
email: new FormControl<string>('test@email.com'),
password: new FormControl<string>('123456'),
createdAt: new FormControl<Date>(new Date())
});
}
}

There’s one more thing to mention about creating FormGroup: you can use FormBuilder to make things even easier.

The FormBuilder provides syntactic sugar that shortens the process of creating instances of a FormControl, FormGroup, or FormArray. It reduces the amount of boilerplate needed to build complex forms.

Here's how you can use it:

constructor(private fb: FormBuilder) {
this.userForm = fb.group<IUserForm>({
id: fb.control<number>(0),
name: fb.control<string>('John'),
email: fb.control<string>('test@email.com'),
password: fb.control<string>('123456'),
createdAt: fb.control<Date>(new Date())
});
}

From here, we can then look to use a tool such as Bit to turn our code into an independent component that we can use and reuse across any projects that require it.

Here are a few useful links from the Angular documentation:

Remember to use types and be happy!

Build Angular Apps with reusable components, just like Lego

Bit’s open-source tool help 250,000+ devs to build apps with components.

Turn any UI, feature, or page into a reusable component — and share it across your applications. It’s easier to collaborate and build faster.

Learn more

Split apps into components to make app development easier, and enjoy the best experience for the workflows you want:

Micro-Frontends

Design System

Code-Sharing and reuse

Monorepo

--

--