From 5d0c4678491441082703c33fe2da256d6f254169 Mon Sep 17 00:00:00 2001 From: "Kevin C. Coram" Date: Wed, 8 Jan 2020 22:05:39 -0500 Subject: [PATCH] Document static method approach --- apps/static-factory-methods/README.md | 87 +++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 apps/static-factory-methods/README.md diff --git a/apps/static-factory-methods/README.md b/apps/static-factory-methods/README.md new file mode 100644 index 0000000..6a743c3 --- /dev/null +++ b/apps/static-factory-methods/README.md @@ -0,0 +1,87 @@ +# Parent Component Creates Form; Child Components Define Structure + +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)](../global-form/README.md) 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. + +```typescript +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. + +## Static Form Builder Methods + +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. + +### Name Component + +```typescript + 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 : ''), + }); + } +``` + +### Address List Component + +```typescript + static buildForm(addresses: Address[]): FormArray { + const list: FormArray = new FormArray([]); + + if (addresses) { + addresses.forEach(addr => { + list.push(AddressComponent.buildForm(addr)); + }); + } + + return list; + } +``` + +### Address Component + +```typescript + 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 : ''), + }); + } +``` + +## Pros + +- The child components encapsulate the form controls and their display, while keeping the form creation logic separate from the actual template rendering +- The child components can easily be re-used + +## Cons + +- The overall shape of the form from the parent component's perspective is not always clear