Another approach for refactoring a component into child sub-components where the parent component is responsible for creating the entre Reactive Form would be to define static factory methods within each child component rather than within a full-fledged service. As with the Parent Component Creates Form and Passes Form Controls Into Child Components (Global Form) approach, the appropriate form controls would be passed into the children.
In many ways, this approach is a hybrid between the Parent Form and Global Form approaches.
export class AppComponent implements OnInit, OnDestroy {
contact: Contact;
form: FormGroup;
private subscription: Subscription;
constructor(private service: ContactService, private fb: FormBuilder) {}
public ngOnInit() {
this.subscription = this.service
.loadContact()
.subscribe((data: Contact) => {
this.contact = data;
this.form = this.fb.group({
name: NameComponent.buildForm(data.name),
addresses: AddressListComponent.buildForm(data.addresses),
});
});
}
}
The HTML templating will be identical to the Global Form approach.
Rather than having a separate factory service, this approach uses static methods on each of the child sub-classes. This approach intentionally couples the logic for creating a sub-form structure with the component that would display it, keeping the logic in one place rather than separating it between components and an otherwise unrelated service. The rule-of-thumb in this approach is that the component which needs to display the form to a user will best know what the structure of that form needs to be.
static buildForm(name: Name): FormGroup {
return new FormGroup({
firstName: new FormControl(name ? name.firstName : ''),
lastName: new FormControl(name ? name.lastName : ''),
middleName: new FormControl(name ? name.middleName : ''),
prefix: new FormControl(name ? name.prefix : ''),
suffix: new FormControl(name ? name.suffix : ''),
});
}
static buildForm(addresses: Address[]): FormArray {
const list: FormArray = new FormArray([]);
if (addresses) {
addresses.forEach(addr => {
list.push(AddressComponent.buildForm(addr));
});
}
return list;
}
static buildForm(addr: Address): FormGroup {
return new FormGroup({
line1: new FormControl(addr ? addr.line1 : ''),
line2: new FormControl(addr ? addr.line2 : ''),
city: new FormControl(addr ? addr.city : ''),
state: new FormControl(addr ? addr.state : ''),
postalCode: new FormControl(addr ? addr.postalCode : ''),
});
}