Was ist der Unterschied zwischen formControlName und FormControl?

97

Ich verwende ReactiveFormsModuleAngular2, um eine Komponente zu erstellen, die ein Formular enthält. Hier ist mein Code:

foo.component.ts :

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

foo.component.html (mit [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 (mit 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>

Beide Wege funktionieren. Aber ich kann nicht herausfinden, was der Unterschied zwischen [formControl]und ist formControlName.

Smartmouse
quelle
1
Ich würde sagen, dass der Hauptgrund für die Verwendung von formControlName gegenüber formControl darin besteht, dass Sie keine einzelnen FormControl-Instanzen in der Komponente verwalten möchten.
Paul Samsotha

Antworten:

176

Ich glaube, Sie haben einen wichtigen Punkt übersehen: die [formGroup]Richtlinie im zweiten Beispiel. formControlNamewird zusammen mit verwendet [formGroup], um Ihr Formular mit mehreren Punktnavigationen zu speichern. Beispielsweise:

<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>

Ist äquivalent zu:

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

Stellen Sie sich jetzt verschachtelt vor FormGroups:)

Harry Ninh
quelle
Die Verwendung von [formControl] = "form.get ('Registration.Attributes.aboutme')" verursachte Probleme. Funktioniert jedoch einwandfrei mit formControlName = "firstNRegistration.Attributes.aboutmeame"
Ricardo Saracino
[formControl]verursacht form.validProbleme während der Validierung mit formGroup, alle Kommentare
Pardeep Jain
Wie kann ich damit umgehen, wenn das Eingabeelement eine andere Komponente ist? Wie binde ich die Kontrolle mit der Komponente
Ramakanth Reddy
20

[formControl]weist der FormControlInstanz, die Sie erstellt haben, einen Verweis zu FormControlDirective.

formControlName Weist dem Formularmodul eine Zeichenfolge zu, um das Steuerelement nach Namen zu suchen.

Wenn Sie Variablen für die Steuerelemente erstellen, benötigen Sie auch nicht die .von Harry erwähnten, aber ich würde auch empfehlen, [formGroup]stattdessen zu verwenden, da dies bei komplizierteren Formularen unübersichtlich werden kann.

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
quelle
wenn ich this.fullName = new FormControl hinzufüge ('', Validators.required); Ich habe einen Fehler erhalten, den Sie nicht zuweisen können, weil er schreibgeschützt oder konstant ist, aber hier werde ich als Variable verwendet. Bitte helfen Sie
Brijesh Mavani
1
Bitte posten Sie die genaue Fehlermeldung. Es ist wahrscheinlich noch besser, eine neue Frage zu erstellen, die Ihren Code enthält, der die Reproduktion ermöglicht
Günter Zöchbauer
7

Es gibt eine dritte Äquivalenz zu den beiden in der akzeptierten Antwort angegebenen: (nicht empfohlen):

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

Beachten Sie, dass wir weiterhin die Direktive [formGroup] verwenden.

Damit diese Vorlage jedoch fehlerfrei kompiliert werden kann, muss Ihre Komponente die Steuerelemente als AbstractControls und nicht als FormControls deklarieren:

myComponent.ts

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

Beachten Sie jedoch, dass das Deklarieren von AbstractControls nicht empfohlen wird. Wenn Sie also den Fehler erhalten, Cannot find control with unspecified name attributeist es wahrscheinlich, dass Sie die Stile gemischt oder Ihre Steuerelemente als AbstractControls deklariert haben.

rmcsharry
quelle
Wie kann ich damit umgehen, wenn das Eingabeelement eine andere Komponente ist? Wie binde ich die Kontrolle mit der Komponente
Ramakanth Reddy
Sie können nicht - auch wenn es einen Weg gibt, sollten Sie nicht. Das Element sollte an das in DIESER KOMPONENTE definierte Steuerelement gebunden sein. Wenn Sie Daten an eine andere Komponente übergeben möchten, verwenden Sie einen Dienst (oder wenn es sich um eine übergeordnete Komponente handelt, dann einen Ereignisemitter). Google, wie man Daten zwischen Komponenten
weitergibt
Kannst
Ramakanth Reddy
2

Aus den Angular-Dokumenten ( https://angular.io/guide/reactive-forms) ):

Komponente

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

Vorlage

<form [formGroup]="profileForm">

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

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

</form>

Beachten Sie, dass genau wie das FormGroupeine Gruppe von Steuerelementen enthält, das profileForm FormGroupmit der FormGroup Direktive an das Formularelement gebunden ist , wodurch eine Kommunikationsschicht zwischen dem Modell und dem Formular mit den Eingaben erstellt wird. Die formControlNamevon der FormControlNameDirektive bereitgestellte Eingabe bindet jede einzelne Eingabe an das in derFormGroup

Chris Halcrow
quelle
1

Mit können [formControl]Sie die Vorteile der reaktiven Programmierung nutzen, da FormControleine Eigenschaft mit dem Namen valueChanges(ich kenne diese derzeit , vielleicht gibt es mehr als diese) eine zurückgibt, Observabledie Sie abonnieren und verwenden können. (Dies ist beispielsweise in Registerszenarien sehr nützlich, in denen Sie überprüfen möchten, ob die Eingabe-E-Mail nicht wiederholt wird, sobald der Benutzer den Wert ändert.)

Seyed Ali Roshan
quelle
Ja. Sie verwenden jedoch weiterhin formControlName in der Vorlage, auch wenn Sie das Modell in Ihrer Antwort verwenden. Weisen Sie einfach formControlName = "someFormControlName" einem FormControl in der Datei component.ts zu, z. B. someFormControlName: FormControl;
Charles Robertson