FormControl In Angular

FormControl In Angular

In this article, We will learn what is FormControl and some of its attributes and methods. The particular HTML form element is set and tracked by FormControl. It is one of the angular forms' building blocks. FormArray and FormGroup are the other two.

What is FormControl

Take a look at a simple text input box.

First Name : <input type="text" name="firstname" /> 

As a developer, you'd like to know what the text box's current value is. You'd also like to know whether the value is correct. If the value(dirty) has been updated by the user or if it has remained unchanged. You want to be alerted if the user modifies the value.

The FormControl is an object that contains all of the data associated with a single input element. It keeps track of the value and status of each of these controls.

FormControl is merely a class. For each form field, a FormControl is produced. We may use our component class to refer to them and check their attributes and methods.

FormControl can be used to change the value of the Form field. Determine the current status of

Using FormControl

There are two methods for creating Angular Forms in Angular. The first is template-driven, whereas the second is Reactive Forms.

To use Angular forms, import the FormsModule (for template-driven forms) and ReactiveFormsModule (for Reactive Forms) from @angular/forms in your route module first.
import { FormsModule, ReactiveFormsModule } from '@angular/forms';

Also, include it in the metadata for imports.
imports: [
   BrowserModule,
   AppRoutingModule,
   FormsModule,
   ReactiveFormsModule
],

Reactive Forms

It is our obligation to design the Model use FormGroup, FormControl, and FormArray in the Reactive Forms methodology.

To use FormControl, we must first import it from the @angular/forms package.
import { FormGroup, FormControl, Validators } from '@angular/forms'

Then make the FormGroup at the top of the hierarchy. The collection of FormControl is the first argument to FormGroup. The FormControl method is used to add them, as seen below.
reactiveForm = new FormGroup({
  firstname: new FormControl('',[Validators.required]),
  lastname: new FormControl(),
  email: new FormControl(),
})

Alternatively, you can use the FormBuilder API.
this.reactiveForm = this.formBuilder.group({
  firstname: ['',[Validators.required]],
  lastname: [''],
  email: [''],
});

Use the formControlName directive to link the form element to the template, as illustrated below.
<form [formGroup]="reactiveForm" (ngSubmit)="onSubmit()" novalidate>
 
  <p>
    <label for="firstname">First Name </label>
    <input type="text" id="firstname" name="firstname" formControlName="firstname">
  </p>
 
  <p>
    <label for="lastname">Last Name </label>
    <input type="text" id="lastname" name="lastname" formControlName="lastname">
  </p>
 
  <p>
    <label for="email">Email </label>
    <input type="text" id="email" name="email" formControlName="email">
  </p>
   
  <p>
    <button type="submit">Submit</button>
  </p>
 
</form>

Template-driven forms

The FormControl is defined in the Template in template-driven forms. The top-level FormGroup is created by the <Form> directive. On each Form element, we use the ngModel directive, which automatically creates the FormControl object.
<form #templateForm="ngForm" (ngSubmit)="onSubmit(templateForm)" novalidate>
 
  <p>
    <label for="firstname">First Name</label>
    <input type="text" name="firstname" ngModel>
  </p>
 
  <p>
    <label for="lastname">Last Name</label>
    <input type="text" name="lastname" ngModel>
  </p>
 
  <p>
    <label for="email">Email </label>
    <input type="text" id="email" name="email" ngModel>
  </p>
 
  <p>
    <button type="submit">Submit</button>
  </p>
  
</form>

To gain a reference to the FormModel in the Component class, use the viewChild. The top-level FormGroup is returned by the NgForm control property.
@ViewChild('templateForm',null) templateForm: NgForm;

Setting the value

setValue()

abstract setValue(value: any, options?: Object): void

To set a new value for the form control, we use the FormControl's setValue or patchValue methods. At the FormControl level, there is no difference between setValue and patchValue.
setEmail() {
  this.reactiveForm.get("email").setValue("sachin.tendulakar@gmail.com");
};


setEmail() {
  this.templateForm.control.get("email").setValue("sachin.tendulkar@gmail.com");
};

patchValue()

abstract patchValue(value: any, options?: Object): void

setEmail() {
  this.reactiveForm.get("email").setValue("sachin.tendulakar@gmail.com");
};

setEmail() {
  this.templateForm.control.get("email").setValue("sachin.tendulkar@gmail.com");
};

Two-way binding

In Template-driven forms, two-way data binding is the preferred method of keeping the component model in sync with the FormModel.
<p>
  <label for="firstname">First Name </label>
  <input type="text" id="firstname" name="firstname" [(ngModel)]="contact.firstname">
</p>

Finding the Value

value

value: any

The value returns the current FormControl value. It's in read-only mode. Use the setValue or patchValue methods to change the value of the control.
//reactive forms
this.reactiveForm.get("firstname").value

//template driven forms
this.templateForm.control.get("firstname").value

valueChanges

valueChanges: Observable<any>

When the value of a control changes, the component broadcasts the valueChanges event. The value may vary when the user edits the UI element or when the setValue/patchValue function is used programmatically. As indicated below, we can subscribe to it.
//reactive Forms
 
this.fNameChange = this.reactiveForm.get("firstname").valueChanges.subscribe(x => {
   console.log(x);
})

In template-driven forms, it's the same.
setTimeout(() => { 
   this.fNameChange = this.templateForm.control.get("firstname").valueChanges.subscribe(x => {
     console.log(x);
   })
});

Control Status

The FormControl keeps track of the HTML Element to which it is bound's validation state. The following is a list of properties connected to status.

status

status: string

When the value of a form control changes, Angular performs validation checks. The control can have four possible states depending on the validation result.

VALID: All validity checks on the FormControl were passed.
INVALID: At least one validation check has failed for this control.
PENDING: This control is currently doing a validation check.
DISABLED: Validation checks are not performed on this control.
//reactive forms
this.reactiveForm.get("firstname").status

//template driven forms
this.templateForm.control.get("firstname").status

valid

valid: boolean

When a control has passed all of the validation checks and is not disabled, it is considered legitimate.
this.reactiveForm.get("firstname").valid

invalid

invalid: boolean

When a control fails one of the validation criteria but is not disabled, it is considered invalid.
this.reactiveForm.get("firstname").invalid

pending

pending: boolean

When a control is doing a validation check, it is considered pending.
this.reactiveForm.get("firstname").pending 

disabled

disable: boolean

When the state of a control is Deactivated, it is disabled.
this.reactiveForm.get("firstname").disabled

enabled

enable: boolean

As long as the status is not DISABLED, control is enabled.
this.reactiveForm.get("firstname").disabled

pristine

pristine: boolean

If the user has not yet updated the value in the UI, the control is clean.
this.reactiveForm.get("firstname").pristine

dirty

dirty: boolean

If the user has changed the value in the UI, the control is dirty.
this.reactiveForm.get("firstname").dirty

touched

touched: boolean

If the control has been marked as touched, this is true. When a user triggers a blur event on a control, it is tagged as touched.
this.reactiveForm.get("firstname").touched

untouched

untouched: boolean

If the control hasn't been marked as touched, this is true. If the user has not yet triggered a blur event on a control, it is considered undisturbed.
this.reactiveForm. get("firstname"). untouched

Changing the Status

The following methods can be used to modify the status of the control programmatically.

When we alter the status of a control programmatically or via UI, the parent control's validity and value are calculated and updated as well. There may be occasions when you do not want this to occur. OnlySelf:true can be used in these situations to ensure that the parent control is not checked.

markAsTouched

This approach indicates that the control has been touched.
markAsTouched(opts: { onlySelf?: boolean; } = {}): void

onlySelf: Only this control is marked if true. If it is false, it will mark all of its direct ancestors as touched as well. False is the default value.
this.reactiveForm.get("firstname").markAsTouched()
this.reactiveForm.get("firstname").markAsTouched({ onlySelf:true; })

markAllAsTouched

Syntax

markAllAsTouched(): void
The control, as well as all descendant controls, is marked as touched.

markAsUntouched

Syntax

markAsUntouched(opts: { onlySelf?: boolean; } = {}): void

The control is marked as undisturbed.

onlySelf: Only this control is marked as untouched if true. Mark all direct ancestors as unaffected if the information is inaccurate or not provided. False is the default value.

markAsDirty

Syntax

markAsDirty(opts: { onlySelf?: boolean; } = {}): void

The control is marked as filthy. When the value of a control is updated via the user interface, it becomes dirty.

onlySelf: If this is the case, only this control will be tagged as dirty; otherwise, all immediate ancestors will be marked as dirty. False is the default value.

markAsPristine

Syntax

markAsPristine(opts: { onlySelf?: boolean; } = {}): void

The control is marked as immaculate.

onlySelf: If this is the case, only this control will be designated as pristine; otherwise, all immediate ancestors will be tagged as pristine. False is the default value.

markAsPending

Syntax

markAsPending(opts: { onlySelf?: boolean; emitEvent?: boolean; } = {}): void

The control is marked as pending. When the control is in the middle of doing a validation check, we label it as pending.

onlySelf: If true, only this control will be marked. Mark all direct ancestors if they are false or not provided. False is the default value.

emitEvent: The statusChanges observable produces an event with the most recent status the control is tagged pending whether true or not specified (the default). When this value is false, no events are generated.

disable

Syntax

disable(opts: { onlySelf?: boolean; emitEvent?: boolean; } = {}): void

The control is turned off. This indicates the control is not subject to validity tests and is not included in any parent's aggregate value. Its current state is DISABLED.

onlySelf: If true, only this control will be marked. Mark all direct ancestors if they are false or not provided. The default value is false.

emitEvent: When the control is disabled, both the statusChanges and valueChanges observables emit events with the most recent status and value, whether true or not given (the default). When this value is false, no events are generated.

enable

Syntax

enable(opts: { onlySelf?: boolean; emitEvent?: boolean; } = {}): void

Allows for control. This indicates that the control is included in validation checks and the parent's aggregate value. Its value and validators are used to recalculate its status.

onlySelf: If true, only this control will be marked. Mark all direct ancestors if they are false or not provided. False is the default value.

emitEvent: When the control is enabled, both the statusChanges and valueChanges observables broadcast events with the most recent status and value, whether true or not supplied (the default). When this value is false, no events are generated.

Status Change Event

statusChanges

Syntax

statusChanges: Observable<any>

By subscribing to the statusChanges event, we may subscribe to the statusChanges event. When the control's validity status is calculated, the event is triggered.
//Reactive Forms
this.reactiveForm.get("firstname").statusChanges.subscribe(x => {
  console.log(x);
})

//Template Driven Forms
this.templateForm.control.get("firstname").statusChanges.subscribe(x => {
   console.log(x);
})

Validation

Whether we use template-driven forms or reactive forms determines how we add validators.

Validators are added to Reactive forms when the controls are declared.
reactiveForm = new FormGroup({
  firstname: new FormControl('',[Validators.required]),
  lastname: new FormControl(),
  email: new FormControl(),
})

While in the template's template-driven forms
<p>
  <label for="firstname">First Name </label>
  <input type="text" id="firstname" name="firstname" ngModel required >
</p>

updateValueAndValidity()

Syntax

updateValueAndValidity(opts: { onlySelf?: boolean; emitEvent?: boolean; } = {}): void

The updateValueAndValidity method makes the form validate itself. This is useful when using setValidators and RemoveValidators to dynamically add and remove validators.

onlySelf: Only update this control if true. Update all direct ancestors if false or not specified. The default value is false.

emitEvent: When the control is updated, both the statusChanges and valueChanges observables broadcast events with the newest status and value, whether true or not supplied (the default). When this value is false, no events are generated.
//reactive forms
this.reactiveForm.get("firstname").updateValueAndValidity();
 
//template driven forms
this.templateForm.control.get("firstname").updateValueAndValidity();

setValidators() / setAsyncValidators()

The sync or async validators are added programmatically. This function will remove any sync or async validators that were previously installed.

Syntax

setValidators(newValidator: ValidatorFn | ValidatorFn[]): void
setAsyncValidators(newValidator: AsyncValidatorFn | AsyncValidatorFn[]): void

//Reactive Form
setValidator() {
  this.reactiveForm.get("firstname").setValidators([Validators.required, Validators.minLength(5)]);
  this.reactiveForm.get("firstname").updateValueAndValidity();
}

//Template driven forms
setValidator() {
  this.templateForm.control.get("firstname").setValidators([Validators.required, Validators.minLength(5)]);
  this.templateForm.control.get("firstname").updateValueAndValidity();
}

clearValidators() / clearAsyncValidators()

Syntax

clearValidators(): void
clearAsyncValidators(): void

All validators are cleared with clearValidators and clearAsyncValidators.
//reactive forms
clearValidation() {
   this.reactiveForm.get("firstname").clearValidators();
   this.reactiveForm.get("firstname").updateValueAndValidity();
}

//template driven forms
clearValidation() {
  this.templateForm.control.get("firstname").clearValidators();
  this.templateForm.control.get("firstname").updateValueAndValidity();
}

errors()

Syntax

errors: ValidationErrors | null

If validation fails, this object contains any errors that are generated, or null if no errors are generated.
getErrors() {
 
  const controlErrors: ValidationErrors = this.reactiveForm.get("firstname").errors;
  if (controlErrors) {
    Object.keys(controlErrors).forEach(keyError => {
      console.log("firtname "+ ' '+keyError);
    });
  }
}

setErrors()

Syntax

setErrors(errors: ValidationErrors, opts: { emitEvent?: boolean; } = {}): void

Example
setErrors() {
    this.reactiveForm.get("firstname").setErrors( {customerror:'custom error'});
}

getError()

Syntax

getError(errorCode: string, path?: string | (string | number)[]): any

Error data for the control with the supplied URL is reported.
this.reactiveForm.getError("firstname")
 
//
this.reactiveForm.getError("address.pincode");
this.reactiveForm.getError(["address","pincode"]);

hasError

Syntax

hasError(errorCode: string, path?: string | (string | number)[]): boolean

Returns true if the control with the supplied path contains the stated error.
this.reactiveForm.hasError("firstname")
 
//
this.reactiveForm.hasError("address.pincode");
this.reactiveForm.hasError(["address","pincode"]);

Reset

Syntax

abstract reset(value?: any, options?: Object): void

The control is reset. The default value can also be given.
this.reactiveForm.get("firstname").reset('');
this.reactiveForm.get("firstname").reset('test');

Conclusion

in this article, We learn what is FormControl and looked at the various methods and properties.

I hope this article helps you and you will like it.👍

If you have any doubt or confusion then free to ask in comment section.

Post a Comment

Previous Post Next Post