Qual é a diferença entre formControlName e FormControl?

97

Estou usando o ReactiveFormsModuleAngular2 para criar um componente que contém um formulário. Aqui está o meu código:

foo.component.ts :

constructor(fb: FormBuilder) {
    this.myForm = fb.group({
        'fullname': ['', Validators.required],
        'gender': []
    });
}

foo.component.html (com [formControl]):

<div class="fields">
    <div class="field">
        <label>Fullname*</label>
        <input type="text" [formControl]="myForm.controls.fullname"/>
    </div>
</div>

<div class="inline fields">
    <label for="gender">Gender</label>
    <div class="field">
        <div class="ui radio checkbox">
            <input type="radio" name="gender" checked="" tabindex="0" class="hidden" [formControl]="myForm.controls.gender">
            <label>Male</label>
        </div>
    </div>
    <div class="field">
        <div class="ui radio checkbox">
            <input type="radio" name="gender" tabindex="0" class="hidden" [formControl]="myForm.controls.gender">
            <label>Female</label>
        </div>
    </div>
</div>

foo.component.html (com formControlName):

<div class="fields">
    <div class="field">
        <label>Fullname*</label>
        <input type="text" formControlName="fullname"/>
    </div>
</div>

<div class="inline fields">
    <label for="gender">Gender</label>
    <div class="field">
        <div class="ui radio checkbox">
            <input type="radio" name="gender" checked="" tabindex="0" class="hidden" formControlName="gender">
            <label>Male</label>
        </div>
    </div>
    <div class="field">
        <div class="ui radio checkbox">
            <input type="radio" name="gender" tabindex="0" class="hidden" formControlName="gender">
            <label>Female</label>
        </div>
    </div>
</div>

Ambas as formas funcionam. Mas não consigo descobrir qual é a diferença entre usar [formControl]e formControlName.

rato inteligente
fonte
1
Eu diria que o principal motivo para usar formControlName em vez de formControl é quando você não deseja manter instâncias individuais de FormControl no componente.
Paul Samsotha,

Respostas:

176

Acredito que você perdeu um ponto importante: [formGroup]diretiva no segundo exemplo. formControlNameé usado junto com [formGroup]para salvar suas navegações de vários pontos do formulário. Por exemplo:

<div>
  <input type="text" [formControl]="myForm.controls.firstName"/>
  <input type="text" [formControl]="myForm.controls.lastName"/>
  <input type="text" [formControl]="myForm.controls.email"/>
  <input type="text" [formControl]="myForm.controls.title"/>
</div>

É equivalente a:

<div [formGroup]="myForm">
  <input type="text" formControlName="firstName"/>
  <input type="text" formControlName="lastName"/>
  <input type="text" formControlName="email"/>
  <input type="text" formControlName="title"/>
</div>

Agora imagine aninhado FormGroups:)

Harry Ninh
fonte
usando [formControl] = "form.get ('Registration.Attributes.aboutme')" causou problemas .. mas funciona bem com formControlName = "firstNRegistration.Attributes.aboutmeame"
Ricardo Saracino
[formControl]causando problema durante a form.validvalidação com formGroup, quaisquer comentários
Pardeep Jain
como posso lidar com se o elemento de entrada é outro componente. como faço para vincular o fomrcontrol com o componente
Ramakanth Reddy
20

[formControl]atribui uma referência à FormControlinstância que você criou para o FormControlDirective.

formControlName atribui uma string para o módulo de formulários para pesquisar o controle por nome.

Se você criar variáveis ​​para os controles, também não precisará do .conforme mencionado por Harry, mas também sugiro usar [formGroup]em vez disso, porque com formulários mais complicados isso pode se tornar confuso.

constructor(fb: FormBuilder) {
    this.fullName = new FormControl('', Validators.required);
    this.gender = new FormControl('');
    this.myForm = fb.group({
        'fullname': this.fullName,
        'gender': this.gender
    });
}
Günter Zöchbauer
fonte
quando adiciono this.fullName = new FormControl ('', Validators.required); Recebi um erro do tipo você não pode atribuir porque é uma propriedade somente leitura ou constante, mas aqui sou considerado uma variável
Portanto
1
Por favor, poste a mensagem de erro exata . Provavelmente é ainda melhor criar uma nova pergunta contendo seu código que permita a reprodução
Günter Zöchbauer
7

Há uma 3ª equivalência com as duas fornecidas na resposta aceita, que é esta (não recomendado):

<div [formGroup]="myForm">
  <input type="text" [formControl]="firstName"/>
  <input type="text" [formControl]="lastName"/>
  <input type="text" [formControl]="email"/>
  <input type="text" [formControl]="title"/>
</div>

Observe que ainda estamos usando a diretiva [formGroup].

No entanto, para que este modelo seja compilado sem erros, seu componente precisa declarar os controles como AbstractControls e não FormControls:

myComponent.ts

firstName: AbstractControl
lastName: AbstractControl
email: AbstractControl
title: AbstractControl

No entanto, observe que declarar AbstractControls não é recomendado , portanto, se você receber o erro Cannot find control with unspecified name attribute, é provável que tenha misturado os estilos ou declarado seus controles como AbstractControls.

rmcsharry
fonte
como posso lidar com se o elemento de entrada é outro componente. como faço para vincular o fomrcontrol com o componente
Ramakanth Reddy
Você não pode - mesmo se houver uma maneira, você não deve. O elemento deve ser vinculado ao controle definido NESSE COMPONENTE. Se você deseja passar dados para outro componente, use um serviço (ou se for um componente pai, então um emissor de evento). Google como transmitir dados entre componentes
rmcsharry
você pode olhar para esta postagem stackoverflow.com/questions/58100248/…
Ramakanth Reddy
2

Dos documentos Angular ( https://angular.io/guide/reactive-forms ):

Componente

@Component({
  ...
})
export class ProfileEditorComponent {
  profileForm = new FormGroup({
    firstName: new FormControl(''),
    lastName: new FormControl(''),
  });
}

Modelo

<form [formGroup]="profileForm">

  <label>
    First Name:
    <input type="text" formControlName="firstName">
  </label>

  <label>
    Last Name:
    <input type="text" formControlName="lastName">
  </label>

</form>

Observe que, assim como FormGroupcontém um grupo de controles, o profileForm FormGroupestá vinculado ao elemento do formulário com a FormGroup diretiva, criando uma camada de comunicação entre o modelo e o formulário que contém as entradas. A formControlNameentrada fornecida pela FormControlNamediretiva liga cada entrada individual ao controle de formulário definido noFormGroup

Chris Halcrow
fonte
1

com [formControl]você pode usar as vantagens da programação reativa porque FormControltem uma propriedade chamada valueChanges(eu conheço esta agora, talvez haja mais do que isso) que retorna um Observableque você pode assinar e usar. (por exemplo, é muito útil em cenários de registro em que você deseja verificar o e-mail de entrada para não ser repetido assim que o usuário alterar o valor)

Seyed Ali Roshan
fonte
Sim. Mas você ainda usa formControlName no modelo, mesmo quando usa o modelo em sua resposta. Apenas atribua o formControlName = “someFormControlName” a um FormControl no arquivo component.ts como someFormControlName: FormControl;
Charles Robertson