I want to create a single big form with angular 2. But I want to create this form with multiple components as the following example shows.
App component
<form novalidate #form1="ngForm" [formGroup]="myForm"> <div> <address></address> </div> <div> <input type="text" ngModel required/> </div> <input type="submit" [disabled]="!form1.form.valid" > </form>
Address component
<div> <input type="text" ngModel required/> </div>
When I use the code above it was visible in the browser as i needed but the submit button was not disabled when I delete the text in address component.
But the button was disabled correctly when I delete the text in input box in app component.
FormGroupDirective is used to Bind an existing FormGroup to a DOM element. Syntax: <form [FormGroup] ="name"> Exported from: ReactiveFormsModule.
Control Value Accessor is an interface that provides us the power to leverage the Angular forms API and create a communication between Angular Form API and the DOM element. It provides us many facilities in angular like we can create custom controls or custom component with the help of control value accessor interface.
I would use a reactive form which works quite nicely, and as to your comment:
Is there any other simple example for this one? Maybe the same example without loops
I can give you an example. All you need to do, is to nest a FormGroup
and pass that on to the child.
Let's say your form looks like this, and you want to pass address
formgroup to child:
ngOnInit() { this.myForm = this.fb.group({ name: [''], address: this.fb.group({ // create nested formgroup to pass to child street: [''], zip: [''] }) }) }
Then in your parent, just pass the nested formgroup:
<address [address]="myForm.get('address')"></address>
In your child, use @Input
for the nested formgroup:
@Input() address: FormGroup;
And in your template use [formGroup]
:
<div [formGroup]="address"> <input formControlName="street"> <input formControlName="zip"> </div>
If you do not want to create an actual nested formgroup, you don't need to do that, you can just then pass the parent form to the child, so if your form looks like:
this.myForm = this.fb.group({ name: [''], street: [''], zip: [''] })
you can pass whatever controls you want. Using the same example as above, we would only like to show street
and zip
, the child component stays the same, but the child tag in template would then look like:
<address [address]="myForm"></address>
Here's a
Demo of first option, here's the second Demo
More info here about nested model-driven forms.
There is a way to do that in template driven forms too. ngModel creates automatically a separate form on each component, but you can inject the form of the parent component by adding this to your component:
@Component({ viewProviders: [{ provide: ControlContainer, useExisting: NgForm}] }) export class ChildComponent
You have to make sure though, that each input has a unique name. So if you use *ngFor to call your child component, you have to put the index (or any other unique identifier) into the name , e.g.:
[name]="'address_' + i"
If you want to structure your form into FormGroups, you use ngModelGroup and
viewProviders: [{ provide: ControlContainer, useExisting: NgModelGroup }]
instead of ngForm and add [ngModelGroup]="yourNameHere"
to some of your child components html containing tags.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With