Angular Form Controls Two-Way Binding?
Published: 2020-09-05 18:29:59

**New Discovery**
Don't use Form Controls, Form Groups, Form Builders, Reactive Forms at all.

Use ngModel instead, read this 3 part series.

{% link https://dev.to/jwp/angular-validation-using-ngmodel-55gf %}

**Consider this HTML**

The Angular FormControl pattern:


```html
<form [formGroup]="formGroup">
   <input
      formControlName="fcSSN"
   />
</form>
```

In Angular, we use form controls to provide validation. We like its simple regex based validation scheme and automatic application of warning colors when values are invalid.

We use the form control value changed event and the valid flag to automatically show and hide the Save button. 

All powerful reasons for using the FormControl.

**The Triad of Values**

There are three values to consider:

-The HTMLInputElement value shown and changed by the user.

-The FormControl Value which tracks user input. 

-The immutable Model Value, to be set 1 time at start and changed only by FormControl event handler.

The guidance from Angular is to avoid direct DOM value manipulation, this leaves us with two options.

**The Model and the Form Control Relationship**

```typescript
// this is the validation pattern
ssnPattern = 
 /(?=.{11}$)\d{1,3}-?\d{1,2}-?\d{1,4}|###-###-###/;
controls = {
  // this is the formControl for the SSN number.
  fcSSN: new FormControl(
   // this.ssn is the model
   this.ssn, 
   // use the regex above for validation
   [Validators.pattern(this.ssnPattern)]),
};
formGroup: FormGroup = 
  new FormGroup(this.controls);
```
From the code above, we can see that the FormGroup encapsulates the FormControl which points to the Model. We also can see the regex which is used to validate the value.

If we set the initial value of the FormContol in ngAfterInit like this:

```typescript
@Input() defaultValue = "###-###-####";
ngAfterViewInit() {
 this.controls.fcSSN.setValue(this.defaultValue);
}
```
We will see this in the View.

![SSN Hash Tags](https://dev-to-uploads.s3.amazonaws.com/i/9p0r3es6btu1jlb89u3p.PNG)

As soon as we type in a value of 1 the ripple effect looks like this from the form control changed event handler.

```css
FormControlValue: "1"
FormControlValueChangeEventValue: "1"
HTMLInputElementValue: "1"
ModelValue: undefined
valid: false

```
In the output shown above, we can see that the form control and HTMLInputElement values are tracking the changes; but the Model is not following along! This means that there is no two-way binding as the model is not updated.

**How to Synch Form Control Changes to the Model**

This new way of doing things is a result of the laws of Immutability; which imply the only time to mutate is right before the valid Save. 

There should be only one place where the model is updated and that's in the change event handler as shown below.

```typescript
this.controls.fcSSN.valueChanges.subscribe((value) => {
   // if valid
   if (this.controls.fcSSN.valid) {
      // update model
      this.ssn = value;
   }
```

> We no longer mutate or use the Model for mutation as the workflow happens. Rather we wait until the new value is deemed valid! 

>All mutation is done in the form control itself. The Typescript logic and HTML only focus on the form controls and not the model!