export class CadastroPessoaComponent implements OnInit, OnDestroy {
formulario: FormGroup;
private destroy$ = new Subject<void>();
// Streams
tipoPessoa$: Observable<TipoPessoa>;
formularioValido$: Observable<boolean>;
botaoClasse$: Observable<string>;
// Definição das regras de validação por tipo
private validacoesPorTipo = {
fisica: [
{ campo: 'nome', validadores: [Validators.required] },
{ campo: 'cpf', validadores: [Validators.required] }
],
juridica: [
{ campo: 'razaoSocial', validadores: [Validators.required] },
{ campo: 'cnpj', validadores: [Validators.required] }
]
};
constructor(private fb: FormBuilder) { }
ngOnInit(): void {
this.inicializarFormulario();
this.configurarStreams();
}
ngOnDestroy(): void {
this.destroy$.next();
this.destroy$.complete();
}
inicializarFormulario(): void {
this.formulario = this.fb.group({
tipoPessoa: ['fisica', Validators.required],
// Campos com validadores iniciais nulos
nome: ['', null],
cpf: ['', null],
razaoSocial: ['', null],
cnpj: ['', null]
});
}
configurarStreams(): void {
// Stream do tipo de pessoa
this.tipoPessoa$ = this.formulario.get('tipoPessoa').valueChanges.pipe(
startWith(this.formulario.get('tipoPessoa').value as TipoPessoa),
distinctUntilChanged(),
tap(tipo => this.atualizarValidadores(tipo as TipoPessoa)),
takeUntil(this.destroy$)
);
// Stream da validade do formulário
this.formularioValido$ = this.formulario.statusChanges.pipe(
map(() => this.formulario.valid),
startWith(this.formulario.valid),
distinctUntilChanged(),
takeUntil(this.destroy$)
);
// Stream da classe do botão
this.botaoClasse$ = this.formularioValido$.pipe(
map(valido => valido ? "botao" : "botao__desabilitado")
);
}
// Função pura para obter validadores por tipo
private getValidadoresPorTipo(tipo: TipoPessoa): ValidacaoCampo[] {
return this.validacoesPorTipo[tipo] || [];
}
// Função pura para obter campos que devem ter validadores limpos
private getCamposParaLimpar(tipo: TipoPessoa): string[] {
return tipo === 'fisica'
? ['razaoSocial', 'cnpj']
: ['nome', 'cpf'];
}
// Aplica validadores de forma funcional
private atualizarValidadores(tipo: TipoPessoa): void {
// Limpa validadores dos campos não relevantes
this.getCamposParaLimpar(tipo)
.forEach(campo => {
const control = this.formulario.get(campo);
control.clearValidators();
control.updateValueAndValidity({emitEvent: false});
});
// Aplica validadores aos campos relevantes
this.getValidadoresPorTipo(tipo)
.forEach(({campo, validadores}) => {
const control = this.formulario.get(campo);
control.setValidators(validadores);
control.updateValueAndValidity({emitEvent: false});
});
}
// Verifica se deve exibir erro em um campo
exibirErro(campo: string): Observable<boolean> {
return this.formulario.statusChanges.pipe(
startWith(''),
map(() => {
const control = this.formulario.get(campo);
return control.invalid && control.touched;
})
);
}
// Ação para salvar o formulário
salvar(): void {
if (this.formulario.valid) {
const dadosTratados = this.tratarDadosFormulario(this.formulario.value);
console.log('Dados a salvar:', dadosTratados);
// Lógica para salvar os dados
}
}
// Função pura para tratar os dados do formulário
private tratarDadosFormulario(formValue: any): any {
const tipo = formValue.tipoPessoa;
const dadosComuns = { tipoPessoa: tipo };
// Filtra apenas os campos relevantes baseado no tipo
return tipo === 'fisica'
? { ...dadosComuns, nome: formValue.nome, cpf: formValue.cpf }
: { ...dadosComuns, razaoSocial: formValue.razaoSocial, cnpj: formValue.cnpj };
}
}