1
votes

My domain model is

vm = { 
  name: 'John Doe', // input in parent form
  account: { // child component with 2 inputs
    acc1: '08', 
    acc2: '6523' 
  } 
};

Parent form is template-driven, looks like

<form #form="ngForm" name="form" novalidate (ngSubmit)="submit(form)">
  <label>Name</label>
  <input type="text" name="name" [(ngModel)]="vm.name" />
  <my-child name="account" [(ngModel)]="vm.account"></my-child>
  <button type="submit">Submit</button>
</form>
<pre>form.value={{form.value | json}}</pre>

Child component has 2 inputs for acc1 and acc2 fields and was written in model-driven way using formGroup, formControlName directives.

As you can see in this plunker, 2-way binding between domain model and child component works ok. I mean initial model values in vm.account are shown in view, model gets updated as user types in input fields.

My question: is it possible to write this child component in template-driven way using ngModel, etc. to make it to work the same way in the parent form? I couldn't figure out how to make the child component to propagate view changes to model.

Edit: Based on accepted answer, above plunker updated to show 2 components, one in reactive way, one in template-driven way.

1

1 Answers

0
votes

I've made template driven form that in fact is nested.

http://plnkr.co/edit/FUmAshW6NDIp44lVCe2y?p=preview

I've changed a bit your plunker, mainly changes are here:

template: `
    <form>
      <label>Account</label>
      <input type="text" name='acc1' [(ngModel)]="accountNumber.acc1"/>
      <input type="text" name='acc2' [(ngModel)]="accountNumber.acc2"/>
    </form>
    <pre>{{accountNumber | json}}</pre>
  `

and in ControlValueAccessor implementation:

  propagateChange = (_: any) => {
  }
  registerOnChange(fn: (value: any) => void) {
     this.propagateChange = fn;
  }

  registerOnTouched() {}