Learn how to inject service into Validator in Angular. The validator may depend on some external service to do its validation. For Example, it may need to fetch data from the back end server to validate the value.
This is a continuation of our following tutorials
Here is our greater than custom validator gte from the previous tutorial. The gte is a function that returns ValidatorFn function.
import { AbstractControl, ValidationErrors, ValidatorFn } from '@angular/forms'
export function gte(val: number): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
let v: number = +control.value;
if (isNaN(v)) {
return { 'gte': true, 'requiredValue': val }
}
if (v <= +val) {
return { 'gte': true, 'requiredValue': val }
}
return null;
}
}
We pass the parameter to the validator in the component class as shown below.
myForm = new FormGroup({
numVal: new FormControl('', [gte(10)]),
})
Let us now see how we can inject service into the above validator. First, move the logic from the gte validator to a separate service.
Create a new service gte.service.ts
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class gteService {
gte(num:any, requiredValue:Number) : Boolean {
if (isNaN(num)) {
return false;
}
if (num <= +requiredValue) {
return false;
}
return true;
}
}
The gteService is very simple.
The gte method takes val and requiredValue as the
parameter. It checks if the val is a number and is greater than requiredValue. If
yes returns true else returns false.
There are two ways you can inject service into the validator. One is to create a wrapper service. The other option is to inject service directly into the validator.
Open the gte.validator.ts. Create the gteValidatorService
class. In the constructor inject the gteService. Copy the validator function
gte into the class and use the gteService as shown below
import { AbstractControl, ValidationErrors, ValidatorFn, Validator, NG_VALIDATORS, FormControl } from '@angular/forms'
import { gteService } from './gte.service';
import { Directive, OnInit, forwardRef, Input, Injectable } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class gteValidatorService {
constructor(private gteService: gteService) {
}
gte(val: number): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
let v: number = +control.value;
if (!this.gteService.gte(v,val)) {
return { 'gte': true, 'requiredValue': val }
}
return null;
}
}
}
Inject the gteValidatorService in the component class and use the validator as shown below.
import { Component } from '@angular/core';
import { FormGroup, FormControl, AbstractControl, ValidationErrors, ValidatorFn } from '@angular/forms'
import { gteValidatorService } from './gte.validator';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
constructor(private gteValidator:gteValidatorService) {
}
myForm = new FormGroup({
numVal: new FormControl('', [this.gteValidator.gte(10)]),
})
get numVal() {
return this.myForm.get('numVal');
}
onSubmit() {
console.log(this.myForm.value);
}
}
Another option is to directly inject the service into the Validator as shown below.
import { AbstractControl, ValidationErrors, ValidatorFn, Validator, NG_VALIDATORS, FormControl } from '@angular/forms'
import { gteService } from './gte.service';
import { Directive, OnInit, forwardRef, Input, Injector } from '@angular/core';
export function gte(val: number): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
let injector = Injector.create([ { provide: gteService, useClass:gteService,deps: []}])
let service = injector.get(gteService);
let v: number = +control.value;
if (!service.gte(v, val)) {
return { 'gte': true, 'requiredValue': val }
}
return null;
}
}
We use the Injector to inject the instance of the service.
let injector = Injector.create([ { provide: gteService, useClass:gteService,deps: []}])
let service = injector.get(gteService);
In this article, we learned how to inject the service into the validator function. One option is to create a Validator service. Copy the validator function into the Validator service. Another option is to inject the service directly into the validator function using the inject method.
Complete List of Angular Forms Tutorial