I have a series of forms (each managed by 1 component).
There is a pattern of inputs in these forms (e.g. many of them require to allow input of an address) that I have to refactor into re-usable components as they are used in multiple forms and I don't want to duplicate neither their logic nor their templates.
Each re-usable component would have to
<form>
tagaddress: {street: "...", "city": "...", ...}
)From this tutorial for Angular2, I understand how to achieve objectives 1, 2 and 4.
The solution in the tutorial allows to achieve also the other objectives, but it does so by doing everything from the parent (see app.component.ts#initAddress
).
How can I achieve 3, 5, 6 and 7, while declaring controls and their constraints within the child?
If you want to provide everything in the child component you can try something like this.
import { Component, Input } from '@angular/core';
import { FormGroupDirective, ControlContainer, Validators, FormGroup, FormControl } from '@angular/forms';
@Component({
selector: 'address',
template: `
<div formGroupName="address">
<input formControlName="city" placeholder="city" (blur)="onTouched" />
<input formControlName="country" placeholder="country" (blur)="onTouched" />
<input formControlName="zipCode" placeholder="zipCode" (blur)="onTouched" />
</div>
`,
styles: [`h1 { font-family: Lato; }`],
viewProviders: [
{ provide: ControlContainer, useExisting: FormGroupDirective }
]
})
export class AddressComponent {
private form: FormGroup;
constructor(private parent: FormGroupDirective) { }
ngOnInit() {
this.form = this.parent.form;
const city = new FormControl('', Validators.required);
const country = new FormControl('', Validators.required);
const zipCode = new FormControl('', Validators.required);
const address = new FormGroup({ city, country, zipCode });
this.form.addControl('address', address);
}
}
Usage:
import { Component } from '@angular/core';
import { FormGroup } from '@angular/forms';
@Component({
selector: 'my-app',
template: `
<form [formGroup]="form">
<address></address>
</form>
{{ form.value | json }}
`,
styleUrls: ['./app.component.css'],
})
export class AppComponent {
form: FormGroup;
constructor() {
this.form = new FormGroup({});
}
}
Please note that I'm using the ReactiveFormsModule
.
Also make sure to check out Angular Forms - Kara Erickson. The presentation shows you how to create a reusable address component with implementations for both, template driven and reactive forms.