Document 'own form controls' application
parent
7280703c4c
commit
b8b2f8a3e7
|
@ -1 +1,83 @@
|
|||
# Components Creating Own Form Controls
|
||||
|
||||
When a component becomes sufficiently complex, or the developer wishes to be able to reuse parts of it elsewhere, the component can be refactored into sub-components. One approach to binding such sub-components to their containing parent component is to pass the parent component's `FormGroup` in as an `@Input` parameter. Additionally, the data that each child sub-component needs is passed into an `@Input`. The children create their own `FormControls` as needed, and add them to the parent `FormGroup` provided to them. This approach greatly simplifies the code and template of the parent component:
|
||||
|
||||
```typescript
|
||||
export class AppComponent implements OnInit, OnDestroy {
|
||||
contact: Contact;
|
||||
form: FormGroup;
|
||||
|
||||
private subscription: Subscription
|
||||
|
||||
constructor(private fb: FormBuilder, private service: ContactService) {
|
||||
this.form = this.fb.group({});
|
||||
}
|
||||
|
||||
public ngOnInit() {
|
||||
this.subscription = this.service.loadContact().subscribe((data: Contact) => {
|
||||
this.contact = data;
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```html
|
||||
<form [formGroup]="form">
|
||||
<nested-forms-name
|
||||
[name]="contact.name"
|
||||
[parent]="form"
|
||||
></nested-forms-name>
|
||||
<nested-forms-address-list
|
||||
[addresses]="contact.addresses"
|
||||
[parent]="form"
|
||||
></nested-forms-address-list>
|
||||
</form>
|
||||
```
|
||||
|
||||
The `nested-forms-name` component is responsible for creating the form controls binding to the Contact's name, and the `nested-forms-address-list` component is responsible for iterating over the Contact's addresses and binding to them using the `nested-forms-address` (singular) component. For example, the `nested-forms-name` would be implented as so:
|
||||
|
||||
```typescript
|
||||
@Component({
|
||||
selector: 'nested-forms-name',
|
||||
templateUrl: './name.component.html',
|
||||
styleUrls: ['./name.component.css']
|
||||
})
|
||||
export class NameComponent implements OnInit {
|
||||
|
||||
@Input() name: Name;
|
||||
@Input() parent: FormGroup;
|
||||
|
||||
group: FormGroup;
|
||||
|
||||
constructor(private fb: FormBuilder) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.group = this.fb.group({
|
||||
firstName: new FormControl(this.name ? this.name.firstName : ''),
|
||||
lastName: new FormControl(this.name ? this.name.lastName : ''),
|
||||
middleName: new FormControl(this.name ? this.name.middleName : ''),
|
||||
prefix: new FormControl(this.name ? this.name.prefix : ''),
|
||||
suffix: new FormControl(this.name ? this.name.suffix : ''),
|
||||
});
|
||||
|
||||
if (this.parent) {
|
||||
this.parent.addControl('name', this.group);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Calling `this.parent.addControl(....)` is what ensures that the controls created in the child component are made part of the over-all form.
|
||||
|
||||
## Pros
|
||||
|
||||
- The parent component is easy to understand and maintain
|
||||
- Each child component encapsulates its form controls and template
|
||||
- The child components can easily be re-used in other "parent" components
|
||||
|
||||
## Cons
|
||||
|
||||
- The creation of the form controls is tightly coupled with the templates
|
||||
- Since each child component encapsulates its form controls, the overall shape of the form data is not always clear
|
||||
|
||||
|
|
Loading…
Reference in New Issue