Forms,Form-validation,FormControl & FromGroup

How to Build a Form,Validation,FormControl,FormGroup in Angular?

Now in our application, we want to create the contact form so we use below ng-cli command to generate all component related data once.

D:\Target Dec-2019\Angular_Application\hello-sagar-jaybhay>ng g c contact-form
CREATE src/app/contact-form/contact-form.component.html (27 bytes)
CREATE src/app/contact-form/contact-form.component.spec.ts (664 bytes)
CREATE src/app/contact-form/contact-form.component.ts (292 bytes)
CREATE src/app/contact-form/contact-form.component.css (0 bytes)
UPDATE src/app/app.module.ts (1307 bytes) 

These are files created by using cli command and added a reference to app.module.ts file.

Now first we build contact form with bootstrap CSS.

<p>contact-form works!</p>

<div class="container-fluid" style="width: 50%">
<form>
<div class="form-group">
    <label for="firstName">First Name</label>
    <input id="firstName" type="text" class="form-control">
</div>
<div class="form-group">
    <label for="comment">Comment</label>
    <textarea id="comment" col=30 rows="10" type="textare" class="form-control"></textarea>
</div>
<div class="form-group">
<button class="btn btn-primary form-control" >Submit</button>
</div>
</form>
</div>

FormControl

Now we need to add validation for our form elements, so in angular, we have FormControl class by using this we will check the value of field,also field is touched or not touched,is value is dirty or not, is value pristine means value is not changed. So for each input field in the form we need control object.

Tracks the value and validation status of an individual form control. In this FormControl class is inherited from AbstractControl class. This is one of the three fundamental building blocks of Angular forms, along with FormGroup and FormArray. It extends the AbstractControl class that implements most of the base functionality for accessing the value, validation status, user interactions, and events.

FormGroup

All the property of formcontrol class are available to FormGroup class means dirty,value,touched,untouched like properties are present in FormGroup.

FormGroup aggregates the values of each child FormControl into one object, with each control name as the key. It calculates its status by reducing the status values of its children. For example, if one of the controls in a group is invalid, the entire group becomes invalid.

FormGroup is one of the three fundamental building blocks used to define forms in Angular, along with FormControl and FormArray.

When instantiating a FormGroup, pass in a collection of child controls as the first argument. The key for each child registers the name for the control.

It will send the value is valid or not if all the elements in form are valid else it will give not valid. So accessing properties of FormGroup are easier than accessing all the elements properties are present on that form.

Forms formvalidation ngModel formControl, Forms,Form-validation,FormControl & FromGroup, Sagar Jaybhay

Difference between Reactive Forms in Angular and Template-Driven forms in Angular?

Reactive Forms Template Driven Forms
Here we have more control over validation logic. Simple Validation present
It is also good for complex forms. It is good for simple forms.
It is good for the Unit Test. It is easier to create
  Less code is required

ngModel

In angular ngModel directive creates the FormControl instance and it will track value, user interaction and also validation status of that respective control. It will keep view sync with the model.

<input ngModel id="firstName" type="text" class="form-control">

It accepts a domain model as an optional Input. If you have a one-way binding to ngModel with [] syntax, changing the value of the domain model in the component class sets the value in the view. If you have a two-way binding with [()] syntax (also known as ‘banana-box syntax’), the value in the UI always syncs back to the domain model in your class.

Now remember ngModel requires name attribute. If you can’t specify the name attribute it will throw an error.

Forms formvalidation ngModel formControl, Forms,Form-validation,FormControl & FromGroup, Sagar Jaybhay

So to avoid this error we simply put name attribute like below.

<input ngModel name="firstName" id="firstName" type="text" class="form-control">

When we add ngModel with name directive on control then angular automatically create an instance of FormControl class and associate with that control.

Now we are going to add change event and for this, we add change event to this input field.

<input ngModel name="firstName" id="firstName" #firstName="ngModel" type="text" (change)="log(firstName)" class="form-control">

To inspect the properties of the associated FormControl (like validity state), export the directive into a local template variable using ngModel as the key (ex: #myVar="ngModel").

#firstName=”ngModel” this is called template variable.

Now you can see below image on change event we get NgModel object.

Forms formvalidation ngModel formControl, Forms,Form-validation,FormControl & FromGroup, Sagar Jaybhay

NgModel is an object and below are the properties of that object. And NgModel is the instance of FormControl class.

1.	NgModel {_parent: NgForm, name: "firstName", valueAccessor: DefaultValueAccessor, _rawValidators: Array(0), _rawAsyncValidators: Array(0), …}
1.	control: FormControl {validator: null, asyncValidator: null, _onCollectionChange: ƒ, pristine: false, touched: true, …}
2.	model: ""
3.	name: "firstName"
4.	update: EventEmitter {_isScalar: false, observers: Array(0), closed: false, isStopped: false, hasError: false, …}
5.	valueAccessor: DefaultValueAccessor {_renderer: DebugRenderer2, _elementRef: ElementRef, _compositionMode: true, onChange: ƒ, onTouched: ƒ, …}
6.	viewModel: "sagar"
7.	_parent: NgForm {submitted: false, _directives: Array(1), ngSubmit: EventEmitter, form: FormGroup}
8.	_rawAsyncValidators: []
9.	_rawValidators: []
10.	_registered: true
11.	asyncValidator: (...)
12.	dirty: (...)
13.	disabled: (...)
14.	enabled: (...)
15.	errors: (...)
16.	formDirective: (...)
17.	invalid: (...)
18.	path: (...)
19.	pending: (...)
20.	pristine: (...)
21.	status: (...)
22.	statusChanges: (...)
23.	touched: (...)
24.	untouched: (...)
25.	valid: (...)
26.	validator: (...)
27.	value: (...)
28.	valueChanges: (...)
29.	__proto__: NgControl

More info on this link-https://angular.io/api/forms/NgModel

Validation Of Input Element

Now if we want to add multiple validation on input field we are added like below.

<label for="firstName">First Name</label>
    <input minlength="3" required pattern="sagar" ngModel name="firstNames" id="firstName" #firstNames="ngModel" type="text" (change)="log(firstNames)" class="form-control">
    <div *ngIf="firstNames.errors?.required">First Name Should required</div>
    <div *ngIf="firstNames.errors?.minlength">First Name minimum length 3 is required</div>
    <div *ngIf="firstNames.errors?.pattern">Pattern should match</div>
    <div class="alert alert-danger" *ngIf="firstNames.touched && !firstNames.valid">First Name is Not Valid</div>

And if validation not matched the output is like below image.

Forms formvalidation ngModel formControl, Forms,Form-validation,FormControl & FromGroup, Sagar Jaybhay

In this we apply html inbuilt validation on control and it is applicable in angular also. So by using errors object we can check the respective validation.

<div *ngIf="firstNames.errors?.required">First Name Should required</div>

So in the above tag in *ngIf we are using firstNames as a template variable and by using that template variable we use errors property of FormControl instance because it creates formcontrol instance why bcoz we use ngModel with name property. If the errors object is not null then it will check the required subfield of that errors object.

Now you want to red the inputbox border to do this we check the CSS and if that all CSS present on that formcontrol we apply style so

.form-control.ng-invalid.ng-touched{
    border: 1px solid red;
}

This is the style by which we apply red border on input text box. The output of this like below.

Forms formvalidation ngModel formControl, Forms,Form-validation,FormControl & FromGroup, Sagar Jaybhay

Form tag in angular

When angular see <form> tag in Html then angular automatically add ngForm directive to that form.

Ngform have output property ngSubmit. In below html of contact form.

<form #f="ngForm" (ngSubmit)="Submit(f)"> 
<div class="form-group">
    <label for="firstName">First Name</label>
    <input minlength="3" required pattern="sagar" ngModel name="firstNames" id="firstName" #firstNames="ngModel" type="text" (change)="log(firstNames)" class="form-control">
    <div *ngIf="firstNames.errors?.required">First Name Should required</div>
    <div *ngIf="firstNames.errors?.minlength">First Name minimum length 3 is required</div>
    <div *ngIf="firstNames.errors?.pattern">Pattern should match</div>
    <div class="alert alert-danger" *ngIf="firstNames.touched && !firstNames.valid">First Name is Not Valid</div>
</div>
<div class="form-group">
    <label for="comment">Comment</label>
    <textarea id="comment" ngModel name="comment" #comment="ngModel" col=30 rows="10" type="textare" class="form-control"></textarea>
</div>
<div class="form-group">
<button class="btn btn-primary form-control" >Submit</button>
</div>
</form>
</div>

In a form tag, we create #f is a template variable and of that form tag we use ngSubmit event for generating the output. Now you can see if we submit that button present on the form the output on a console we get.

Forms formvalidation ngModel formControl, Forms,Form-validation,FormControl & FromGroup, Sagar Jaybhay
1.	NgForm {submitted: true, _directives: Array(2), ngSubmit: EventEmitter, form: FormGroup}
1.	form: FormGroup {validator: null, asyncValidator: null, _onCollectionChange: ƒ, pristine: true, touched: false, …}
2.	ngSubmit: EventEmitter {_isScalar: false, observers: Array(1), closed: false, isStopped: false, hasError: false, …}
3.	submitted: true
4.	_directives: (2) [NgModel, NgModel]
5.	control: FormGroup
6.	controls: (...)
7.	dirty: (...)
8.	disabled: (...)
9.	enabled: (...)
10.	errors: (...)
11.	formDirective: (...)
12.	invalid: (...)
13.	path: (...)
14.	pending: (...)
15.	pristine: (...)
16.	status: (...)
17.	statusChanges: (...)
18.	touched: (...)
19.	untouched: (...)
20.	valid: (...)
21.	value: (...)
22.	valueChanges: (...)
23.	__proto__: ControlContainer

This is the form object of FormGroup class and has some same properties as the FormControl instance object like ngModel.

In this form object value is JSON object by which we can get value from our form and it is a key-value representation of that form element. Also remember the name we assign is taken into consideration while getting the value.

NgModelGroup

This directive can only be used as a child of NgForm (within <form> tags).

Use this directive to validate a sub-group of your form separately from the rest of your form, or if some values in your domain model make more sense to consume together in a nested object.

Provide a name for the sub-group and it will become the key for the sub-group in the form’s full value. If you need direct access, export the directive into a local template variable using ngModelGroup (ex: #myGroup="ngModelGroup").

In angular, we have two classes to check state of input field and their validity.

  1. FormControl
  2. FormGroup
  1. FormControl:- it will check only one input field like input text box, textarea like that. When we apply ngModel to input field angular create instance of FormControl and associate that with this input field.
  2. FormGroup:- It is used to represent the entire form and also an option we have to make a group within a form. ngForm directive automatically apply to all form element. So this will automatically create formgroup object and associate that with that form. By using this formgroup object we can check the state changes of that form and its validity.

What is the difference between ngModelGroup and ngForm?

In this ngForm have output property ngSubmit by using this we able to submit the form and this property is not present in the ngModelGroup. So ngModelGroup not able to submit the value as a part of a form.

How to disable button till form is completely filled or valid?

<button class="btn btn-primary form-control" [disabled]="!f.valid">Submit</button>

In the above code, we use disabled attribute and in this we check form is valid or not. F is template variable of respective form and it is used to check the validation of all control at once.

ngValue is used to select a complete object.

<option *ngFor="let m of contactMethods" [value]="m.id" [ngValue]="m">{{m.name}}</option>

Credit-link,link2

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *