Simplified Angular Reactive Forms
Tags: angular, rxweb, webdev, typescript
Published: 2020-03-30 17:17:37

As we all know, Front end applications acquire lot of forms including basic and complex forms which we construct for various purpose like registering user's information, editing it, logging feedback and a lot more

While working with angular forms we first need to decide the type of form we want to make and the most preferred among them are `Reactive forms` because reactive forms allows multiple control to group, validate them and also provides advance form facilities like nested form groups and form arrays 

Now, Imagine if you have a reactive form which needs all the above requirements with necessary validations just as the form shown below:

![Reactive-form](https://dev-to-uploads.s3.amazonaws.com/i/y828h983ul9lzz5w3f5j.gif)

## The Component 
Looking at the reactive features and validations used, it looks like the component must be having a lengthy code with lots of custom functions having custom business logic for performing the validations for array validation, comparing fields. The answer is No!!!

Have a look at the component code

```js
   export class UserAddComponent implements OnInit {
    userFormGroup: FormGroup

    constructor(
        private formBuilder: RxFormBuilder
    ) { }

    ngOnInit() {
        let user = new User();
        user.hobbies = new Array<Hobby>();
        user.address = new Address();
        let hobby = new Hobby();
        user.hobbies.push(hobby);
        this.userFormGroup = this.formBuilder.formGroup(user);
        }

    addAddress(){
      let addresses = this.userFormGroup.controls.hobbies as FormArray;
      addresses.push(this.formBuilder.formGroup(Hobby));
    }
}
```

This is achieved with the help of using `formGroup` method of `RxFormBuilder` which groups the controls which are the properties of the model class.

`RxFormBuilder` is a part of [@rxweb/reactive-form-validators](https://www.npmjs.com/package/@rxweb/reactive-form-validators).
 RxWeb contains various methods for form reset, globally bind error message strategy, patch value, strongly typed reactive forms and a wide range of validations including compose validation, compare validation, unique validation, async validation and tempate driven validation and a lot more. For more information on how to achieve it have a look at this article on [New way to validate angular reactive forms](https://medium.com/@oojhaajay/new-way-to-validate-the-angular-reactive-form-2c4fe4f13373)

## The Model
The source code file where the properties and validations are managed is the  model class. In this approach the controls are not managed at the component level but managed at the model level because this file is considered base root for managing the properties which strengthens you to take advantage of the object oriented concepts into typescript, Other benefit of model class is that its properties can be used as a control in other components as well which means code can be reused and the complexity level of your component decreases. 
 
![Dependency-Diagram](https://dev-to-uploads.s3.amazonaws.com/i/dub5tt7j55tvaag1y2j4.png)
  
The model class file is as below:

```js
import { email,unique,alpha,compare,prop, propArray, propObject } from "@rxweb/reactive-form-validators"

export class Hobby {
  @unique()
  hobbyName: string;
}

export class  Address{
  @prop()
  city: string;

  @prop()
  country: string;
}

export class User {

  @alpha()
  firstName: string;

  @alpha()
  lastName: string;

  @email()
  email: string;

  @prop()
  password: string;

  @compare({fieldName:"password"})
  confirmPassword: string;

  @propObject(Address)
  address: Address;

  @propArray(Hobby)
  hobbies: Hobby[];
}

```

## Html
The controls of the formGroup are finally bind as an input for rendering them into the Html DOM which are further used for getting input from the user. In case of validations to display the validation messages we need to write `*ngIf` conditions for touched, invalid, dirty etc... But here i have used just one condition which will display my errorMessage whenever the state of form is invalid. Here is my complete HTML code.

```js
<form *ngIf="userFormGroup" [formGroup]="userFormGroup">
<div class="form-group">
   <label>FirstName</label>
   <input type="text" formControlName="firstName" class="form-control" />
   <small class="form-text text-danger" *ngIf="userFormGroup.controls.firstName.errors">{{userFormGroup.controls.firstName.errors.alpha.message}}<br/></small>	
</div>
<div class="form-group">
   <label>LastName</label>
   <input type="text" formControlName="lastName" class="form-control" />
   <small class="form-text text-danger" *ngIf="userFormGroup.controls.lastName.errors">{{userFormGroup.controls.lastName.errors.alpha.message}}<br/></small>
</div>
<div class="form-group">
   <label>Email</label>
   <input type="text" formControlName="email" class="form-control" />
   <small class="form-text text-danger" *ngIf="userFormGroup.controls.email.errors">{{userFormGroup.controls.email.errors.email.message}}<br/></small>	
</div>
<div class="form-group">
   <label>Password</label>
   <input type="password" formControlName="password" class="form-control" />
</div>
<div class="form-group">
   <label>Confirm Password</label>
   <input type="password" formControlName="confirmPassword" class="form-control" />
   <small class="form-text text-danger" *ngIf="userFormGroup.controls.confirmPassword.errors">{{userFormGroup.controls.confirmPassword.errors.compare.message}}<br/></small>	
</div>
<div class="card">
   <div class="card-header"><label class="card-title">Address</label>
   </div>
   <div class="card-body">
      <div  [formGroup]="userFormGroup.controls.address">
         <div class="form-group">
            <label>City</label>
            <input type="text" formControlName="city" class="form-control" />
         </div>
         <div class="form-group">
            <label>Country</label>
            <input type="text" formControlName="country" class="form-control" />
         </div>
      </div>
   </div>
</div>
<div class="card">
   <div class="form-group">
      <div class="card-header">
         <label class="card-title">Hobbies</label>
         <button (click)="addAddress()" class="pull-right"><i class="fa fa-plus"></i></button>
      </div>
      <div class="card-body"  [formGroup]="hobby" *ngFor="let hobby of userFormGroup.controls.hobbies.controls; let i = index">
      <label>{{i+1}} Hobby</label>
      <input  type="text" formControlName="hobbyName" class="form-control" />
      <small class="form-text text-danger" *ngIf="hobby.controls.hobbyName.errors">{{hobby.controls.hobbyName.errors.unique.message}}<br/></small>
   </div>
</div>
</div>
<button (click)="onSubmit()" [disabled]="!userFormGroup.valid" class="btn btn-primary">Submit</button>
<br/>
{{userFormGroup.value | json}}
</form>
```  

Here is the complete example on [stackblitz](https://stackblitz.com/edit/angular-29398n-xttknp?file=src/app/prop-array-add.component.html). Feel free to share your feedback, you can also give your suggestion on [gitter](https://gitter.im/rxweb-project/rxweb) channel.