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

Validador assíncrono em formulário de edição.

Estou tentando fazer um validador assíncrono em um formulário que também serve para edição, porém quando eu tento abrir o formulário com o validador ocorrem vários erros. Eu segui todos os passos de criação do validador de acordo com a aula, no formulário para adicionar, o validador funciona perfeitamente, já na de edição não. O que eu queria saber é se tem alguma forma de resolver o problema no formulário de edição .

A baixo alguns erros que correm quando tento abrir o formulário de edição.

HostFormComponent_Host.ngfactory.js? [sm]:1 ERROR TypeError: Cannot read property 'pipe' of undefined
    at FormControl.validator (check-host-name.validator.service.ts:14)
    at FormControl.push../node_modules/@angular/forms/fesm5/forms.js.AbstractControl._runValidator (forms.js:2831)
    at FormControl.push../node_modules/@angular/forms/fesm5/forms.js.AbstractControl.updateValueAndValidity (forms.js:2807)
    at new FormControl (forms.js:3117)
    at FormBuilder.push../node_modules/@angular/forms/fesm5/forms.js.FormBuilder.control (forms.js:6007)
    at FormBuilder.push../node_modules/@angular/forms/fesm5/forms.js.FormBuilder._createControl (forms.js:6047)
    at forms.js:6033
    at Array.forEach (<anonymous>)
    at FormBuilder.push../node_modules/@angular/forms/fesm5/forms.js.FormBuilder._reduceControls (forms.js:6032)
    at FormBuilder.push../node_modules/@angular/forms/fesm5/forms.js.FormBuilder.group (forms.js:5964)
HostFormComponent.html:3 ERROR Error: formGroup expects a FormGroup instance. Please pass one in.

       Example:


    <div [formGroup]="myGroup">
      <input formControlName="firstName">
    </div>

    In your class:

    this.myGroup = new FormGroup({
       firstName: new FormControl()
    });
    at Function.push../node_modules/@angular/forms/fesm5/forms.js.ReactiveErrors.missingFormException (forms.js:1391)
    at FormGroupDirective.push../node_modules/@angular/forms/fesm5/forms.js.FormGroupDirective._checkFormPresent (forms.js:5103)
    at FormGroupDirective.push../node_modules/@angular/forms/fesm5/forms.js.FormGroupDirective.ngOnChanges (forms.js:4926)
    at checkAndUpdateDirectiveInline (core.js:20640)
    at checkAndUpdateNodeInline (core.js:21908)
    at checkAndUpdateNode (core.js:21870)
    at debugCheckAndUpdateNode (core.js:22504)
    at debugCheckDirectivesFn (core.js:22464)
    at Object.eval [as updateDirectives] (HostFormComponent.html:4)
    at Object.debugUpdateDirectives [as updateDirectives] (core.js:22456)
5 respostas

Fala aí Marcelo, tudo bem?

Um de seus problemas para ser na linha 14 do CheckHostNameValidatorService.

O outro parece ser na hora de abrir o formulário, possívelmente não está sendo passado um FormGroup para o [formGroup] do form.

Consegue postar o código do seu Service, HTML e Componente? Ficaria mais fácil tentar ajudar.

Fico no aguardo.

Opa, Matheus

O código a seguir é do serviço do validador

import { Injectable } from '@angular/core';
import { ManageHostsService } from '../../../providers/manage/hosts/hosts.service';
import { AbstractControl } from '@angular/forms';
import { debounceTime, switchMap, first, map, tap } from 'rxjs/operators';

@Injectable({ providedIn: 'root' })
export class CheckHostNameValidatorService {
  constructor(private hostService: ManageHostsService) { }

  checkHostName() {
    let findHost;
    return (control: AbstractControl) => {
      return control.valueChanges
        .pipe(debounceTime(1000))
        .pipe(switchMap(list => {
          findHost = list;
          return this.hostService.list();
        }))
        .pipe(map(hosts => {
          var count = 0;
          hosts.forEach(val => {
          if(val.name === findHost)
            count++
          });
          return (count>0)? true : false;
        }))
        .pipe(map(isFind => isFind ? {checkHostExists : true } : null))
        .pipe(tap(r => console.log(r)))
        .pipe(first());
    }
  }
}

Esse aqui é o html

<mat-dialog-content class="mat-typography" scrollStrategy="false">
  <div fxLayout="column">
    <div fxLayout="row wrap" fxLayoutAlign="center none">
      <form [formGroup]="formHost">
        <mat-tab-group mat-align-tabs="center">
          <mat-tab label="Padrão">
            <mat-form-field class="input-full-width">
              <input formControlName="name" matInput placeholder="Nome">
              <mat-error *ngIf="formHost.get('name').errors?.required">
                Necessário informar um nome de host!
              </mat-error>
              <mat-error *ngIf="formHost.get('name').errors?.checkHostExists">
                Já existe um host com o mesmo nome!
              </mat-error>
            </mat-form-field>
          </mat-tab>
        </mat-tab-group>
      </form>
    </div>
  </div>
</mat-dialog-content>
<mat-dialog-actions align="end">
  <button mat-button mat-dialog-close>Cancel</button>
  <button *ngIf="data.action == 'UPDATE'" [disabled]="formHost.invalid || formHost.pending" (click)="submitFormUpdate()" color="primary" mat-raised-button cdkFocusInitial>Atualizar</button>
  <button *ngIf="data.action == 'CREATE'" [disabled]="formHost.invalid || formHost.pending" (click)="submitForm()" color="primary" mat-raised-button cdkFocusInitial>Enviar</button>
</mat-dialog-actions>

E esse é o componente


import { Component, OnInit, Inject } from '@angular/core';
import { FormGroup, FormBuilder, Validators, FormArray, FormControl } from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialogRef, MatSnackBar } from '@angular/material';
import { HostModel } from 'src/app/shared/model/host-model/host.model';
import { CheckHostNameValidatorService } from '../../admin-shared/validator/manage/hosts/check-host-name.validator.service';
import { Observable } from 'rxjs';

@Component({
  selector: 'app-host-form',
  templateUrl: './host-form.component.html',
  styleUrls: ['./host-form.component.css']
})

export class HostFormComponent implements OnInit {
  formHost: FormGroup;
  host: HostModel;
  constructor(
    private formBuilder: FormBuilder,
    @Inject(MAT_DIALOG_DATA) public data: any,
    private checkHostService: CheckHostNameValidatorService
    ) {
      this.host = new HostModel(data.host);
    }

  ngOnInit() {
    this.formHost = this.formBuilder.group({
      name: [this.host.name, Validators.required, this.checkHostService.checkHostName()],
    })
  }
}
solução!

Fala aí Marcelo, tudo bem? O problema essa no seu service, veja a linha:

return control.valueChanges
        .pipe(debounceTime(1000))

Você está tentando acessar o .pipe de valueChanges, mas, esse valueChanges está undefined, por isso está acontecendo o problema.

Só não consegui identificar o problema, olhando os seus códigos tudo parece estar correto, além disso, está dando erro no seu .html do HostFormComponent na linha 3, o que também é estranho, pois olhando o HTML tudo parece estar correto.

Consegue zipar o projeto, subir no Google Drive e compartilhar comigo ou se tiver no Github me manda o link? Vai ser mais fácil tentar achar o problema.

matheus.castiglioni@caelum.com.br

Fico no aguardo,

Agente conseguiu resolver o problema aqui, só modificando o mecanismo de verificação aos dados digitados. No caso de ser um formulário de edição a primeira ação a ser realizada seria buscar a lista de hosts e já fazer a comparação, já no caso de ser formulário de adição a gente faz o .pipe no .valueChanges da forma como deve ser.

Mesmo assim obrigada por tudo, valeu cara.

Mágina, precisando não deixe de criar suas dúvidas.