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