I particularly like using Reactive Forms for development in Angular. The validation example I'm going to introduce is using Reactive Forms.
Create the validator that Angular will use for validation. In my case I created the following class with the CPF validator.
Remember that the method should return {key: value} when it has error and null when not.
export class GenericValidator {
constructor() {}
/**
* Valida se o CPF é valido. Deve-se ser informado o cpf sem máscara.
*/
static isValidCpf(): ValidatorsFn {
return (control: AbstractControl): Validators => {
const cpf = control.value;
if (cpf) {
let numbers, digits, sum, i, result, equalDigits;
equalDigits = 1;
if (cpf.length < 11) {
return null;
}
for (i = 0; i < cpf.length - 1; i++) {
if (cpf.charAt(i) !== cpf.charAt(i + 1)) {
equalDigits = 0;
break;
}
}
if (!equalDigits) {
numbers = cpf.substring(0, 9);
digits = cpf.substring(9);
sum = 0;
for (i = 10; i > 1; i--) {
sum += numbers.charAt(10 - i) * i;
}
result = sum % 11 < 2 ? 0 : 11 - (sum % 11);
if (result !== Number(digits.charAt(0))) {
return { cpfNotValid: true };
}
numbers = cpf.substring(0, 10);
sum = 0;
for (i = 11; i > 1; i--) {
sum += numbers.charAt(11 - i) * i;
}
result = sum % 11 < 2 ? 0 : 11 - (sum % 11);
if (result !== Number(digits.charAt(1))) {
return { cpfNotValid: true };
}
return null;
} else {
return { cpfNotValid: true };
}
}
return null;
};
}
In the creation of the formGroup you should set the validator that Angular will use.
export class formComponent implements OnInit {
form: formGroup;
constructor(private formBuilder: FormBuilder) {}
ngOnInit() {
this.form = this.formBuilder.group({
cpf: this.formBuilder.control({ value: null, disabled: false}, GenericValidator.isValidCpf())
})
}
}
And then just put the HTML to display the error. A very simple way to start would be:
<form>
<div>
<label>CPF</label>
<input type="text" formControlName="cpf"/>
</div>
<div *ngIf="form.get('cpf').getError('cpfNotValid')">
O cpf não é válido.
</div>
</form>