¿Cuál es la diferencia entre formControlName y FormControl?

97

Estoy usando ReactiveFormsModuleAngular2 para crear un componente que contiene un formulario. Aquí está mi código:

foo.component.ts :

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

foo.component.html (con [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 (con 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 formas funcionan. Pero no puedo entender cuál es la diferencia entre usar [formControl]y formControlName.

smartmouse
fuente
1
Yo diría que la razón principal para usar formControlName sobre formControl es cuando no desea mantener instancias individuales de FormControl en el componente.
Paul Samsotha

Respuestas:

177

Creo que se perdió un punto importante: la [formGroup]directiva en el segundo ejemplo. formControlNamese utiliza junto con [formGroup]para guardar su formulario de navegación de múltiples puntos. Por ejemplo:

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

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

Ahora imagina anidado FormGroups:)

Harry Ninh
fuente
el uso de [formControl] = "form.get ('Registration.Attributes.aboutme')" causó problemas ... pero funciona bien con formControlName = "firstNRegistration.Attributes.aboutmeame"
Ricardo Saracino
[formControl]causando problemas durante la form.validvalidación con formGroup, cualquier comentario
Pardeep Jain
¿Cómo puedo manejar si el elemento de entrada es otro componente? ¿Cómo enlazo el fomrcontrol con el componente
Ramakanth Reddy
20

[formControl]asigna una referencia a la FormControlinstancia que creó al FormControlDirective.

formControlName asigna una cadena para que el módulo de formularios busque el control por nombre.

Si crea variables para los controles, tampoco necesita las .que menciona Harry, pero también sugiero usarlas [formGroup]en su lugar porque con formas más complicadas esto puede volverse complicado.

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
fuente
cuando agrego this.fullName = new FormControl ('', Validators.required); Tengo un error como que no puede asignar la propiedad de sólo lectura o constante porque es, pero aquí me llevan como variable.So favor ayuda
user8478
1
Publique el mensaje de error exacto . Probablemente sea incluso mejor crear una nueva pregunta que contenga su código que permita reproducirlo
Günter Zöchbauer
7

Hay una tercera equivalencia a las dos proporcionadas en la respuesta aceptada, que es esta (no recomendada):

<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 todavía estamos usando la directiva [formGroup].

Sin embargo, para que esta plantilla se compile sin errores, entonces su componente debe declarar los controles como AbstractControls y no FormControls:

myComponent.ts

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

Sin embargo, tenga en cuenta que no se recomienda declarar AbstractControls , por lo que si obtiene el error Cannot find control with unspecified name attribute, es probable que haya mezclado los estilos o haya declarado sus controles como AbstractControls.

rmcsharry
fuente
¿Cómo puedo manejar si el elemento de entrada es otro componente? ¿Cómo enlazo el fomrcontrol con el componente
Ramakanth Reddy
No puede, incluso si HAY una manera, no debería hacerlo. El elemento debe estar vinculado al control definido EN ESE COMPONENTE. Si desea pasar datos a otro componente, utilice un servicio (o si es un componente principal, entonces un emisor de eventos). Google cómo pasar datos entre componentes
rmcsharry
¿Puedes mirar esta publicación? stackoverflow.com/questions/58100248/…
Ramakanth Reddy
2

De los documentos de 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>

Tenga en cuenta que así como FormGroupcontiene un grupo de controles, profileForm FormGroupestá vinculado al elemento de formulario con la FormGroup directiva, creando una capa de comunicación entre el modelo y el formulario que contiene las entradas. La formControlNameentrada proporcionada por la FormControlNamedirectiva vincula cada entrada individual al control de formulario definido en elFormGroup

Chris Halcrow
fuente
1

con [formControl]puede usar las ventajas de la programación reactiva porque FormControltiene una propiedad llamada valueChanges(conozco esta en este momento, tal vez haya más que eso) que devuelve una Observableque puede suscribirse y usar. (por ejemplo, es muy útil en escenarios de registro en los que desea verificar que el correo electrónico de entrada no se repita tan pronto como el usuario cambie el valor)

Seyed Ali Roshan
fuente
Si. Pero aún usa formControlName en la plantilla, incluso cuando usa el modelo en su respuesta. Simplemente asigne formControlName = "someFormControlName" a un FormControl en el archivo component.ts como someFormControlName: FormControl;
Charles Robertson