Dynamic self-registered FormControl in Angular
Angular is very flexible framework, that’s the power! We can use different ways to do same things.
Example for start
We have a list of items with FormGroup, it should looks like checklist, and we should make it works.
Some component with ckecklist:
some.component.html<p>Checklist:</p><app-check-list [list]=”list$ | async”></app-check-list>
Component for checklist:
check-list.component.html<ul [formGroup]=”formGroup”> <li *ngFor=”let item of list”> <input [formControlName]=”item” type=”checkbox” [id]=”item” /> <label [for]=”item”>{{ item }}</label> </li></ul>check-list.component.ts@Component({ selector: ‘app-check-list’, templateUrl: ‘./check-list.component.html’, styleUrls: [‘./check-list.component.css’], changeDetection: ChangeDetectionStrategy.OnPush,})export class CheckListComponent { @Input() list: string[];
readonly formGroup = new FormGroup({});}
At this moment example shows an error, because our FormGroup is empty and we use controls within.
Static declaring FormGroup
If you go static way to declare FormGroup, it should for example looks like:
readonly formGroup = new FormGroup({ apple: new FormControl(), banana: new FormControl(), orange: new FormControl(), grape: new FormControl(), kiwi: new FormControl(),});
And then if the list property has same values: [‘apple’, ‘banana’, ‘orange’, ‘grape’, ‘kiwi’], — example would works well.
But it works for static, what if we don’t know our list of controls? Then we need dynamic solution.
Dynamic declaring FormGroup
Here is how example should look for a dynamic solution:
readonly formGroup = new FormGroup({});
Keep FormGroup empty as at start.
check-list.component.html<ul [formGroup]=”formGroup”> <li *ngFor=”let item of list”> <input
[formControl]=”newFormControl(item)”
type=”checkbox”
[id]=”item” /> <label [for]=”item”>{{ item }}</label> </li></ul>
FormGroup in Angular has method registerControl, which returns registered control. That’s all we need! Just add newFormControl() method to component:
check-list.component.ts...export class CheckListComponent {... readonly formGroup = new FormGroup({});... newFormControl(field: string): FormControl { return this.formGroup.registerControl(field, new FormControl()) as FormControl; }}
Now every control register itself in the FormGroup.
Thanks.