Skip to content

Instantly share code, notes, and snippets.

@thurow
Forked from odahcam/README.md
Created September 20, 2018 23:11
Show Gist options
  • Save thurow/2514bec46c23aee3f3f2db51600f7901 to your computer and use it in GitHub Desktop.
Save thurow/2514bec46c23aee3f3f2db51600f7901 to your computer and use it in GitHub Desktop.
Validação de CPF e CNPJ com integração com React Forms, implementado com Angular 6.

Exemplos

Uso com reactive forms

new FormGroup({
    cpf: new FormControl('', [
        Validators.required,
        Validators.pattern(/^(\d{3}\.){2}\d{3}\-\d{2}$/),
        Validators.minLength(14),
        Validators.maxLength(14),
        CpfCnpjValidator.validate,
    ]),
});

Uso com template driven forms

Inclua a directive CpfCnpjValidatorDirective no módulo onde você deseja utilizá-la e use +- como o seguinte:

<mat-form-field appearance="outline">

    <mat-label>CPF</mat-label>
    <input matInput name="cpf" type="tel" appCpfCnpjValidate length="14" [textMask]="maskCpfOptions" placeholder="000.000.000-00">

    <mat-hint align="start" *ngIf="formSignInGroup.get('cpf').invalid">xxx.xxx.xxx-xx</mat-hint>
    <mat-hint align="end">{{ getNumericCharsLength(formSignInGroup.get('cpf').value) }} / 11</mat-hint>

    <mat-error align="start" *ngIf="formSignInGroup.get('cpf').hasError('digit')">CPF inválido.</mat-error>

</mat-form-field>

Referências

import { Directive } from '@angular/core';
import { Validator, NG_VALIDATORS, AbstractControl, ValidationErrors } from '@angular/forms';
import { CpfCnpjValidator } from '@shared/cpf-cnpj.validator';
@Directive({
selector: '[appCpfCnpjValidate][ngModel]',
providers: [{
provide: NG_VALIDATORS,
useExisting: CpfCnpjValidatorDirective,
multi: true
}]
})
export class CpfCnpjValidatorDirective extends CpfCnpjValidator implements Validator {}
import { Validator, NG_VALIDATORS, AbstractControl } from '@angular/forms';
import { ValidationErrors } from '@angular/forms';
export class CpfCnpjValidator implements Validator {
static cpfLength = 11;
static cnpjLength = 14;
/**
* Calcula o dígito verificador do CPF ou CNPJ.
*/
static buildDigit(arr: number[]): number {
const isCpf = arr.length < CpfCnpjValidator.cpfLength;
const digit = arr
.map((val, idx) => val * ((!isCpf ? idx % 8 : idx) + 2))
.reduce((total, current) => total + current) % CpfCnpjValidator.cpfLength;
if (digit < 2 && isCpf) {
return 0;
}
return CpfCnpjValidator.cpfLength - digit;
}
/**
* Valida um CPF ou CNPJ de acordo com seu dígito verificador.
*/
static validate(c: AbstractControl): ValidationErrors | null {
const cpfCnpj = c.value.replace(/\D/g, '');
// Verifica o tamanho da string.
if ([CpfCnpjValidator.cpfLength, CpfCnpjValidator.cnpjLength].indexOf(cpfCnpj.length) < 0) {
return { length: true };
}
// Verifica se todos os dígitos são iguais.
if (/^([0-9])\1*$/.test(cpfCnpj)) {
return { equalDigits: true };
}
// A seguir é realizado o cálculo verificador.
const cpfCnpjArr: number[] = cpfCnpj.split('').reverse().slice(2);
cpfCnpjArr.unshift(CpfCnpjValidator.buildDigit(cpfCnpjArr));
cpfCnpjArr.unshift(CpfCnpjValidator.buildDigit(cpfCnpjArr));
if (cpfCnpj !== cpfCnpjArr.reverse().join('')) {
// Dígito verificador não é válido, resultando em falha.
return { digit: true };
}
return null;
}
/**
* Implementa a interface de um validator.
*/
validate(c: AbstractControl): ValidationErrors | null {
return CpfCnpjValidator.validate(c);
}
}
@JoeKyy
Copy link

JoeKyy commented Sep 7, 2019

Nesta parte;
if (digit < 2 && isCpf) { return 0; }

Para funcionar CNPJ com o primeiro ou segundo (exemplo: 22.289.665/0001-08 / 44.623.381/0001-30) digito 0, tem que ser:
if (digit < 2 && isCpf) { return 0; } else if (digit < 2) { return 0; }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment