Solucionado (ver solução)
Solucionado
(ver solução)
1
resposta

Função de validação assincrona não é chamada

Pessoal, estou com uma situação no minimo "estranha ou intrigante"....

Seguindo a aula de validações assincronas, construi a classe de serviço para verificar se o usuário existe e fiz o registro da função junto ao formBuilder como manda o figurino, só que a validação não é executada e a chamada remota não é feita. Também não acontece é exposto nenhum erro no console do navegador.

Visando evitar qualquer desleixo, baixei também o projeto disponivel no inicio da aula 04 e realizei novamente os procedimentos e o mesmo sintoma, o validador é reconhecido, mas a função não é executada, como se o controle não fosse passado e a função não fosse executada.

Pra validar esse cenário, eu inclui duas mensagens de console.log no método da classe de serviço UsuarioExiste() conforme apresentado abaixo:

usuario-existe.service.ts

import { AbstractControl } from '@angular/forms';
import { NovoUsuarioService } from './novo-usuario.service';
import { Injectable } from '@angular/core';
import { first, map, switchMap } from 'rxjs/operators';

@Injectable({
  providedIn: 'root',
})
export class UsuarioExisteService {
  constructor(private novoUsuarioService: NovoUsuarioService) {}

  usuarioJaExiste() {
    console.log('Capturando função assincrona de validação...');
    return (controle: AbstractControl) => {
      console.log('manipulando o controle recebido....');
      return controle.valueChanges.pipe(
        switchMap((nomeUsuario) =>
          this.novoUsuarioService.verificaUsuarioExistente(nomeUsuario)
        ),
        map((usuarioExiste) =>
          usuarioExiste ? { usuarioExistente: true } : null
        ),
        first()
      );
    };
  }
}

Abaixo segue um print da tela do navegador com o console aberto, observem que o método principal que fornece a função foi chamado pelo formBuilder registrando a função assincrona, só que o método que recebe o AbstractControl não foi!! Mesmo digitando o nome de usuário.. Verifiquei também a aba network e nenhuma chamada XHR foi realizada! Veja no entanto que a validação personalizada de minusculo executou, garantindo que o as propriedades de formGroup e formControlName estão corretas.

Foto do formulario de usuário com o console do navegador apresentando apenas uma das duas mensagens definidas

Segue abaixo código do componente e do template para comparação

novo-usuario.component.ts

.....
  ngOnInit(): void {
    this.novoUsuarioForm = this.formBuilder.group({
      email: ['', [Validators.required, Validators.email]],
      fullName: ['', [Validators.required, Validators.minLength(4)]],
      userName: [
        '',
        [minusculoValidator],
        [this.usuarioExisteService.usuarioJaExiste()],
      ],
      password: [''],
    });
  }
.....
}

novo-usuario.component.html

<h4 class="text-center">Registre-se e mostre seu pet ao mundo!</h4>

<form class="form mt-4" [formGroup]="novoUsuarioForm" (submit)="cadastrar()">
  ....
  <div class="form-group">
    <input
      placeholder="Usuário"
      class="form-control"
      formControlName="userName"
    />
    <app-mensagem
      *ngIf="
        novoUsuarioForm.get('userName')?.errors?.minusculo &&
        novoUsuarioForm.get('userName')?.touched
      "
      mensagem="Usuário deve ser em letras minusculas"
    ></app-mensagem>
    <app-mensagem
      *ngIf="novoUsuarioForm.get('userName')?.errors?.usuarioExistente"
      mensagem="Usuário já existe"
    ></app-mensagem>
  </div>
....

  <button class="btn btn-primary btn-block">Cadastro</button>
</form>

<p>Já um usuário? <a [routerLink]="['']"> Faça Login</a></p>

PS: Extrai partes do código dessas ultimas duas classes deve ao limite de caracteres, porém os arquivos completos estão disponiveis no projeto.

Por ultimo, segue o link do código do projeto da aplicação cliente zipado disponibilizado no github https://github.com/fabiosales1983/alura/raw/main/gatitobook.zip

Obs: Sou usuário linux, mas acredito que não seja problema porque a aplicação no final das contas é um javascript e roda no navegador que o meu caso são:

Chrome: Version 105.0.5195.125 (Official Build) (64-bit) Firefox: 105.0.3 (64-bit)

Ambos com o mesmo comportamento.....

Help!

1 resposta
solução!

Pessoal, descobri o problema!!

Segui o curso e na aula seguinte quando construimos o comportamento de cadastrar o usuário, me deparei com a situação em que o botão de submeter o formulário não habilitava, então removi o [disabled] e a função também não executa mas quando pedia o console.log(this.novoUsuarioForm.errors) obtinha o valor null, coloquei então pra logar o formBuilder console.log(this.novoUsuarioForm) e percebi que o estado fo formulario estava invalido.

Fiz uma busca no google sobre "angular formgroup invalid but no errors" e encontrei o topico abaixo no stackoverflow em que a sugestão é de percorrer cada um dos elementos e verificar seu estado individualmente.

https://stackoverflow.com/questions/45220073/how-to-find-the-invalid-controls-in-angularv2-onwards-reactive-form

Fazendo isso pelo console mesmo, descobri que o campo userName continha no atributo errors o seguinte valor: { minusculo: false } e de fato, ao inves de retornar "null", eu estava retornando um objeto mas com o valor false.

minusculo.validator.ts

import { AbstractControl } from '@angular/forms';

export function minusculoValidator(control: AbstractControl) {
  const valor = control.value as string;
  if (valor !== valor.toLowerCase()) {
    return { minusculo: true };
  }
  return { minusculo: false };
}

Essa situação para a clausula *ngIf funciona, mas pelo fato do campo estar com erro, acredito que impedia de realizar a validação seguinte do grupo de assincronos.

Alteri o código para retornar null e a validação funcionou....