10
votes

I am trying to create a complex reactive form with nested component that is populated with a data object.

The behavior I am trying to achieve is very similar to the two-way data binding of a template-driven form: when the user edits an input of the form, the data object is changing automatically.

but as opposed to template-driven form, I cannot use [(ngModel)] because it is deprecated in reactive forms for angular V6.

I know that fromGroup.patchValue() will only do a one way binding and then ill have to manually subscribe to change events and update the data object manually - this will result in a lot of tiring code.

Is there any workaround for that scenario?

2
Your form.value object has already the last form value, why would you need ngModel ?ibenjelloun
form.value will be updated, but not the original source data. for example if I set the value of the 'name' formControl with the value of data['name'], and the user changed the name, the value in data['name'] will still contain the original value.Idan Abrashkin
i don't know why this change either, now i will need to re verbose code with a lot get and sets that wasn't needed before..Hllink
This is really a step backwards. Reactive forms have no good way to do twoway binding anymore. Seriously, now I have to look a the form values and update the model manually. Especially with nested object modelling that are not easily accessible. Previously I only had to worry once and then do all the databinding. That was it.Michelangelo

2 Answers

5
votes

Well if I understand you correctly I had a similar problem what I did (I really don't know if this is the best practice)but it's work for me so in the HTML:

<mat-form-field class="mat-container">
    <input matInput  [formControl]="generalDiscount" type="number" 
        formControlName="generalDiscount" 
        (input)="course.amounts.generalDiscount = $event.target.value" <-the workaround 
        placeholder="Discount" required="required">
</mat-form-field>

This input makes it two way binding and in your .ts class you need to put the same field in your form group like

this.amountGroup = this._formBuilder.group({

    [this.course.amounts.fitToNomberOfPeople,Validators.required],
    generalDiscount:[this.course.amounts.generalDiscount,Validators.required],

});

hope that helps

0
votes

Some kind of workaround.

Proposition is to use (input) event. formControl1 updates own value and writes its value to formControl2 with additional '@example.com' text also. Changing formControl2 value updates own value and updates formControl1 with striped '@example.com' text.

import { Component } from '@angular/core';
import {FormControl} from '@angular/forms';

@Component({
  selector: 'app-template-and-reactive-form',
  template: '<input #inp1 [ngModel]="formControl1.value" ' +
    '(input)="formControl1.setValue(inp1.value);formControl2.setValue(inp1.value+\'@example.com\')" ><br>\n' +
    '<input #inp2 [ngModel]="formControl2.value" ' +
    '(input)="formControl2.setValue(inp2.value);formControl1.setValue(inp2.value.replace(\'@example.com\',\'\'))"><br>\n' +
    'formControl1 value: {{formControl1.value}}<br>\n' +
    'formControl2 value: {{formControl2.value}}<br>',
  styleUrls: ['./template-and-reactive-form.component.scss']
})
export class TemplateAndReactiveFormComponent  {
  formControl1 = new FormControl('');
  formControl2 = new FormControl('');
}