nested-forms/apps/static-factory-methods
Kevin C. Coram 5d0c467849
Document static method approach
2020-01-08 22:13:07 -05:00
..
src Use OnPush change detection strategy 2020-01-08 21:33:38 -05:00
README.md Document static method approach 2020-01-08 22:13:07 -05:00
browserslist Add fourth approach: Static methods on child components 2020-01-04 09:42:53 -05:00
jest.config.js Add fourth approach: Static methods on child components 2020-01-04 09:42:53 -05:00
tsconfig.app.json Add fourth approach: Static methods on child components 2020-01-04 09:42:53 -05:00
tsconfig.json Add fourth approach: Static methods on child components 2020-01-04 09:42:53 -05:00
tsconfig.spec.json Add fourth approach: Static methods on child components 2020-01-04 09:42:53 -05:00
tslint.json Add fourth approach: Static methods on child components 2020-01-04 09:42:53 -05:00

README.md

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) 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.

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

  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

  static buildForm(addresses: Address[]): FormArray {
    const list: FormArray = new FormArray([]);

    if (addresses) {
      addresses.forEach(addr => {
        list.push(AddressComponent.buildForm(addr));
      });
    }

    return list;
  }

Address Component

  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