Solucionado (ver solução)
Solucionado
(ver solução)
4
respostas

AsyncValidator com Edição de dados

Bom dia, segui os passos da aula 4 do curso 2 de angular, e funcionou corretamente para o formulário que adiciona um usuário. Possuindo um validador assíncrono como o mostrado no vídeo mas para não ter emails duplicados.

Porém ao criar um formulário para editar um usuário existente passando as informações do usuário antigo como base me gerou problemas.

    ngOnInit(): void {
        this.userForm = this.formBuilder.group({
            email: [data.email, 
                [
                    Validators.required,
                    Validators.email
                ], 
        this.userValidatorService.checkEmailTaken(data.email)
            ],
            fullName: [data.name, 
                [
                    Validators.required,
                    Validators.minLength(2),
                    Validators.maxLength(40)
                ]
            ],

Após colocar o 'data.email' para inicializar o formulário com o campo preenchido, gerou erro indicando que o valueChanges é null e por isso não possui a propriedade .pipe ;

Então coloquei uma verificação no valueChanges para prevenir este erro.

checkEmailTaken(editValue) {
    return (control: AbstractControl) => {
      if (control.valueChanges) {
        return control.valueChanges
          .pipe(debounceTime(300))
          .pipe(switchMap((plcName) =>  this.plcService.getPLCByName(plcName)))
          .pipe(
            map((isTaken) =>
              isTaken.length > 0 ? { emailTaken: true } : null
            )
          )
          .pipe(tap((r) => console.log(r)))
          .pipe(first());
      }

O erro parou, porém o não consigo enviar o formulário a não ser que troque o e-mail por outro, gostaria de poder realizar a verificação em que o valor no campo e-mail passe, ou se não for duplicado, como no formulário de adição , ou se for igual ao e-mail atual que é passado pelo parâmetro 'editValue'.

Alguém poderia me ajudar com esta duvida?

4 respostas

Fala ai André, tudo bem? Desculpa, mas, não sei se entendi o problema.

O problema é quando você inicializa o formulário com algum valor, esses valores não são validados, é isso? Ai quando você edita o campo email a validação acontece.

Consegue compartilhar o projeto comigo? Assim fica mais fácil eu simular o problema por aqui e analisá-lo com mais calma.

Pode compartilhar através do Github ou Google Drive (zipado), se tiver API compartilha ela junto.

Espero ter ajudado.

Obrigado pela resposta Matheus, infelizmente eu não tenho autorização para compartilhar o projeto. Contudo o erro é facilmente simulado na aplicação alurapic do curso, que pode ser baixada neste link: https://caelum-online-public.s3.amazonaws.com/1501-testes-angular/01/projeto_inicial.zip

Então em app>home>signup>signup.component.ts substituir o campo userName por este:

            userName: ['André', 
                [
                    Validators.required,
                    lowerCaseValidator,
                    Validators.minLength(2),
                    Validators.maxLength(30)
                ],
                this.userNotTakenValidatorService.checkUserNameTaken()
            ],

Note que só inicializei o campo como André, o que seria utilizado neste caso para possibilitar o usuário editar o user já criado; Isto resultará no erro citado que ocorrerá no "userNotTakenValidatorService.checkUserNameTaken()".

Além do erro gostaria de passar o 'André' como parâmetro, checkUserNameTaken('André'), fazendo o validador passar ou se o usuário estiver disponível(igual original), ou se for igual ao usuário atual, no caso André.

solução!

Consegui solucionar a questão!

Impedi o control.valueChanges de dar erro o testando antes além de adicionar outras duas condições, para validar caso o valor esteja em branco e validar caso o valor do formulário de editar seja igual o atual.

user.validator.service.ts

checkUserNameTaken(setValue) {
    return (control: AbstractControl) => {
      if (control.value && control.valueChanges && control.value !== setValue) {
        return control.valueChanges
          .pipe(debounceTime(1000))
      --- código omitido ----
      } else {
        return of(null);
      }

desta forma se inicializar o formulário com um valor o mesmo não será barrado.

user-form.component.ts

 userName: [
          'André',
          null,
          this.userManagmentValidatorService.checkUserNameTaken('André'),
        ],

Compartilho aqui minha solução, para que possa ajudar caso outras pessoas que encontrarem esta mesma dificuldade.

Boa André, fico feliz que tenha resolvido o problema e obrigado por compartilhar.

Desculpa não ter conseguido ajudar à tempo, não tive tempo de simular o erro por aqui e analisá-lo com calma.

Sempre que precisar não deixe de criar suas dúvidas.

Abraços e bons estudos.