Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FormControl / FormGroup / FormArray value type

I want my FormControl (FormGroup / FormArray) be strongly typed so when I have e.g.

interface SomeSource {
  id: string;
  name: string;
}

and I transformed it to e.g.

let form = new FormGroup<SomeSource>({
  id: new FormControl('test id'),
  name1: new FormControl('test name')
});

TypeScript had thrown an error: the name is not found on FormGroup.

Also in the ideal world the form.value should be of SomeSource type (and not any).

Problem is that there is no way to specify this generic type for any AbstractFormControl child.

I think this is fairly easy to override FormGroup with an own interface. However, is there a way to achieve this just using Angular? If no, are there third party solutions?

Motivation: I want to easily refactor my SomeSource. Currently when I refactor SomeSource interface, the form is not adapted and no error is thrown => there is a room for some bugs.

like image 700
smnbbrv Avatar asked Jan 24 '17 14:01

smnbbrv


People also ask

Can FormArray contains FormGroup?

A FormArray can contain any type of controls inside it, and this includes plain form controls, FormGroup instances and even other FormArray instances.

How do I declare FormArray in FormGroup?

We do not have a name to the FormGroup . The Index of the element is automatically assigned as the name for the element. Hence we use the [formGroupName]="i" where i is the index of the FormArray to bind the FormGroup to the div element. Finally, we add the controls using the formControlName directive.

How do you set values on FormArray?

setValue() sets the value of the FormArray . We need to pass an array that matches the structure of the control. Create a sample FormArray . myFormArray = new FormArray([ new FormControl(), new FormControl(), new FormControl() ]);

What is the base class for FormControl FormGroup and FormArray?

AbstractControllink. This is the base class for FormControl , FormGroup , and FormArray .


1 Answers

There is an elegant solution for your problem - leverage TypeScript declaration files (*.d.ts) to introduce generic interfaces extending the standard form classes like AbstractControl, FormControl, etc. It doesn’t introduce any new functionality and has no footprint in the compiled JavaScript, but at the same time enforcing strong type checking.

It was suggested by Daniele Morosinotto in March this year and there are talks now to include it in Angular 9.

Adopting the solution is straightforward:

  1. Download TypedForms.d.ts from this gist and save it as src/typings.d.ts in your project (Angular 6+ already knows how to use this file).
  2. Start using the new types (FormGroupTyped<T>, FormControlTyped<T>, etc.) whenever you need a strong type validation (see examples in that gist or stackblitz).

For more information, check out a blog post analysing available solutions for strongly typed forms.

like image 170
Alex Klaus Avatar answered Sep 26 '22 13:09

Alex Klaus