FormRecord in Angular Forms

The FormRecord is a collection of FormControl. It is very similar to FormGroup and like FormGroup it tracks the value and validity state of a group of FormControl instances. Angular introduced the Typed Forms in Angular 14. With the typed forms it becomes difficult to add FormControl dynamically to a FormGroup. Hence the FormRecord is created for the sole purpose of adding a new FormControl dynamically with dynamic keys. In this article, we will learn what is FormRecord is and learn some of its important properties & methods.

What is FormRecord

FormRecord is intended for situations where we want to add or remove controls dynamically with dynamic keys. FormRecord accepts one generic argument, which describes the type of the controls it contains. This will ensue type safety by restricting all controls in the FormRecord to have the same value type.

FormGroup and FormRecord are fairly similar. You can see from the definition of FormRecord that it extends the FormGroup. Hence we can use FormRecord in the same way we use FormGroup.

FormRecord is a new class introduced in Angular 14 for typed reactive forms. It does not have a equivalent in Template Driven Forms.

Why it was needed

Angular introduced typed forms in Angular 14., which allowed us to assign type to our form.

To create a Typed Form, you can either initialize the form at the time of declaration or create a custom type.

The code below declares the myForm and initializes it at the same time. The Angular will infer its type from the initialization.

Source Code

The myForm contains two FormControl<string | null> properties key1 & key2.

Now, when we try to add a new control at run time with the key test, the Angular compiler throws an error. This is because the key test is not in the inferred type of myForm.

Another way to create a custom type is by making use of Interfaces in TypeScript. The code below creates a new custom type IForm.

Use the newly created type to declare the MyForm.

And then initialize the MyForm in ngOnInit.

Since, the key test is not part of the interface, the code below gives us an compile error.

One way is to declare the optional key test in the interface IForm. That requires us to know the keys ahead of time, which is not possible when we add controls dynamically at run time.

We can also declare the type as any or untypedFormGroup.

In both the above cases, you are not using the types, which would defeat the very purpose of using the Typed forms.

This is where FormRecord steps in. It allows us to add new controls at runtime with dynamic keys and also keeps the benefit of the type system.

How to use FormRecord

The example uses the Angular 17 and standalone components

The code below creates an Angular Form of type FormControl<string|null>. We also suffix the mainForm with ! other wise it will result in an Property 'mainForm' has no initializer and is not definitely assigned in the constructor error.

To add a new FormControl dynamically, we invoke the addControl method passing a new instance of FromControl with a key bar.

In the template assign the mainForm to formGroup directive to display the Form. We use the mainForm.value to read the values of the form just like we do it with the FormGroup.

How to use FormRecord in Angular

Complete Source code is on stackblitz.com

We can add another control using the addControl method.

Controls can be removed using the removeControl method and using the key

Our FormRecord is of type FormControl<string|null>. Hence adding FormControl with the value 0 will result in compile error

Dynamically adding Controls to FormRecord

In this example, we will show you how to add controls dynamically to a FormRecord.

Create a FormRecord and an array to hold designations.

In ngOnInit hook loop through the designations array and add the FormControl instance to the FormRecord using the addControl method.

Create a form to capture the new designation to add to our form.

In the addDesignation method, push the new designation to the designations array and also add new control to the mainForm.

Finally, in the template use the ngFor directive to loop through the designations and insert the input field for each control

You can download the Source Code.

Adding FormControl dynamically to FormRecord

We can further extend the above example to include option to remove the designation.

In the example below, removeDesignation method uses the removeControl method to remove the FormControl from the mainForm.

We can also simplify the code and remove the need for maintaining the designation array, by directly reading the keys from the FormRecord

Which will also simplifies the addDesignation method.

Finally, add the option to remove the designation in the template by invoking the removeDesignation method using event binding.

Source Code

Dynamically removing FormControl

FormRecord Vs FormArray

Both FormRecord and FormArray allows us to add or remove FormControl‘s at runtime. Both tracks the value & validity of their controls and help us the manage them.

The difference is how they are structured. In FormRecord controls becomes a property of the FormRecord. Each control is represented as key-value pair, while in FormArray, the controls become part of an array.

Hence we can manage the controls in the FormRecord using the keys, While in FormArray we need to track them using the array index or using some other technique.

This makes FormRecord ideal for situations where you need to add the new FormControl whose keys are known only at runtime.

FormRecord Vs FormGroup

FormRecord extends FormGroup and hence is very similar. Both Manage the FormControl instance as a key-value pair.

We cannot add FormControl to FormGroup at runtime as we need to declare the type of FormGroup upfront. FormRecord on the other hand is designed to add new FormControl as a key-value pair without breaking the type checking.

Summary

FormRecord comes is very useful in situations where we work with open ended dynamic FormControl’s. It gives more flexibility in managing the controls.

Reference

FormRecord

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Scroll to Top