Error de Angular2: no hay una directiva con "exportAs" establecido en "ngForm"

109

Estoy en el RC4 y recibo el error No hay una directiva con "exportAs" establecido en "ngForm" debido a mi plantilla:

<div class="form-group">
        <label for="actionType">Action Type</label>
        <select
            ngControl="actionType" 
      ===>  #actionType="ngForm" 
            id="actionType" 
            class="form-control" 
            required>
            <option value=""></option>
            <option *ngFor="let actionType of actionTypes" value="{{ actionType.label }}">
                {{ actionType.label }}
            </option>
        </select> 
    </div>

el boot.ts:

import {disableDeprecatedForms, provideForms} from '@angular/forms'; 

 import {bootstrap} from '@angular/platform-browser-dynamic';
 import {HTTP_PROVIDERS, Http} from '@angular/http';
 import {provideRouter} from '@angular/router';

import {APP_ROUTER_PROVIDER} from './routes';

import {AppComponent} from './app.component';

bootstrap(AppComponent, [ disableDeprecatedForms(), provideForms(), APP_ROUTER_PROVIDER, HTTP_PROVIDERS]);

/// así que aquí está mi DropdownList:

<fieldset ngControlGroup="linkedProcess" >
                     <div ngControlGroup="Process" >
                         <label>Linked Process</label>
                          <div class="form-group">       
        <select 
            ngModel
            name="label" 
            #label="ngModel" 
            id="label" 
            class="form-control" required
            (change)="reloadProcesse(list.value)" 
            #list>
            <option value=""></option>
            <!--<option value=`{{ActionFormComponent.getFromString('GET'')}}`></option>-->                 
            <option *ngFor="let processus of linkedProcess?.processList?.list; let i = index" 
            value="{{ processus[i].Process.label}}">
                {{processus.Process.label}}
            </option>
        </select> 
        </div>
     </div>

// mi componente ts:

lo estaba representando en las formas antiguas como esta:

 categoryControlGroups:ControlGroup[] = [];
     categories:ControlArray = new ControlArray(this.categoryControlGroups);

y ahora estoy haciendo esto:

categoryControlGroups:FormGroup[] = [];
     categories:FormArray = new FormArray(this.categoryControlGroups);

¿Crees que es la causa del problema?

Anna
fuente
Qué versión estás usando? ¿Repasaste los formularios?
acdcjunior

Respuestas:

98

Desde 2.0.0.rc6 :

formularios : en desuso provideForms()y disableDeprecatedForms()se han eliminado las funciones. En su lugar, importe el FormsModuleo el ReactiveFormsModulede @angular/forms.

En breve:

Entonces, agregue a suapp.module.ts o equivalente:

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule, ReactiveFormsModule } from '@angular/forms'; // <== add the imports!
 
import { AppComponent }  from './app.component';
 
@NgModule({
  imports: [
    BrowserModule,
    FormsModule,                               // <========== Add this line!
    ReactiveFormsModule                        // <========== Add this line!
  ],
  declarations: [
    AppComponent
    // other components of yours
  ],
  bootstrap: [ AppComponent ]
})
export class AppModule { }

No tener uno de estos módulos puede provocar errores, incluido el que enfrenta:

No se puede enlazar a 'ngModel' ya que no es una propiedad conocida de 'input'.

No se puede enlazar a 'formGroup' ya que no es una propiedad conocida de 'form'

No hay ninguna directiva con "exportAs" establecido en "ngForm"

Si tiene dudas, puede proporcionar tanto el FormsModulecomo el ReactiveFormsModulejuntos, pero son completamente funcionales por separado. Cuando proporcione uno de estos módulos, las directivas de formularios predeterminados y los proveedores de ese módulo estarán disponibles para toda la aplicación.


ngControl¿ Utiliza formularios antiguos ?

Si tiene esos módulos @NgModule, tal vez esté usando directivas antiguas, como ngControl, lo cual es un problema, porque no hay ninguna ngControlen los nuevos formularios. Fue reemplazado más o menos * por ngModel.

Por ejemplo, el equivalente a <input ngControl="actionType">es <input ngModel name="actionType">, así que cámbielo en su plantilla.

Del mismo modo, la exportación en controles ngFormya no es , es ahora ngModel. Entonces, en su caso, reemplace #actionType="ngForm"con #actionType="ngModel".

Entonces, la plantilla resultante debe ser ( ===>s donde se haya cambiado):

<div class="form-group">
    <label for="actionType">Action Type</label>
    <select
  ===>  ngModel
  ===>  name="actionType" 
  ===>  #actionType="ngModel" 
        id="actionType" 
        class="form-control" 
        required>
        <option value=""></option>
        <option *ngFor="let actionType of actionTypes" value="{{ actionType.label }}">
            {{ actionType.label }}
        </option>
    </select> 
</div>

* Más o menos, porque no toda la funcionalidad de ngControlse trasladó a ngModel. Algunos simplemente fueron eliminados o ahora son diferentes. Un ejemplo es el nameatributo, el mismo caso que está teniendo en este momento.

acdcjunior
fuente
gracias por tu respuesta, cuando la cambio tengo el error No se puede asignar a una referencia o variable ¿te dice algo?
Anna
Hmm ... puede que esté en otro lugar. ¿Tienes alguno <input>dentro de un *ngFor? (Probablemente no va a funcionar, pero probar esto y dime si el mensaje desaparece: <option *ngFor="let actionType of actionTypes; let i = index" value="{{ actionTypes[i].label }}"> {{ actionTypes[i].label }} </option>)
acdcjunior
¿Tiene algún <input> dentro de un *ngFor?
acdcjunior
Intente cambiar el nombre de la variable dentro de *ngFora algo diferente a actionType, ¿algo bueno?
acdcjunior
no, no, pero tengo una lista desplegable de selección que estoy iterando, no sé si es la fuente del error, por favor, eche un vistazo a mi pregunta actualizada ...
Anna
61

Me enfrenté al mismo problema. Me había perdido la etiqueta de importación del módulo de formularios en app.module.ts

import { FormsModule } from '@angular/forms';

@NgModule({
    imports: [BrowserModule,
        FormsModule
    ],
Chandan
fuente
2
gracias por esto, funcionó bien, pero debería ser app.module.ts no app.module.component.ts
Salim
Esto no me funciona a pesar de que ya puse la importación de FormsModule en mi módulo de aplicación
emirhosseini
9

Tuve el mismo problema que se resolvió agregando FormsModule a .spec.ts:

import { FormsModule } from '@angular/forms';

y luego agregando la importación a beforeEach:

beforeEach(async(() => {
  TestBed.configureTestingModule({
    imports: [ FormsModule ],
    declarations: [ YourComponent ]
  })
.compileComponents();
}));
Juha Ristolainen
fuente
5

Si recibe esto en su lugar:

Error: errores de análisis de plantilla:

No hay ninguna directiva con "exportAs" establecido en " ngModel "

Lo cual se informó como un error en github , entonces probablemente no sea un error, ya que podría:

  1. tiene un error de sintaxis (por ejemplo, un corchete adicional :) [(ngModel)]]=, O
  2. ser mezclado directivas formas reactivas , tales como formControlName, con la ngModelDirectiva . Esto "ha quedado obsoleto en Angular v6 y se eliminará en Angular v7" , ya que mezcla ambas estrategias de formulario, lo que lo convierte en:
  • parece ngModelque se está utilizando la directiva real , pero de hecho es una propiedad de entrada / salida nombrada ngModelen la directiva de forma reactiva que simplemente se aproxima (parte de) su comportamiento. Específicamente, permite obtener / configurar el valor e interceptar eventos de valor. Sin embargo, algunas de ngModellas otras características , como retrasar las actualizaciones con ngModelOpciones o exportar la directiva, simplemente no funcionan (...)

  • este patrón combina estrategias basadas en plantillas y formas reactivas, que generalmente no recomendamos porque no aprovecha todos los beneficios de ninguna de las estrategias . (...)

  • Para actualizar su código antes de la v7, querrá decidir si seguir con las directivas de formulario reactivo (y obtener / establecer valores usando patrones de formularios reactivos) o cambiar a directivas basadas en plantillas .

Cuando tienes una entrada como esta:

<input formControlName="first" [(ngModel)]="value">

Mostrará una advertencia sobre estrategias de formas mixtas en la consola del navegador:

Parece que estás usando ngModelen el mismo campo de formulario que formControlName.

Sin embargo, si agrega ngModelcomo valor en una variable de referencia, ejemplo:

<input formControlName="first" #firstIn="ngModel" [(ngModel)]="value">

A continuación, se activa el error anterior y no se muestra ninguna advertencia sobre la combinación de estrategias.

CPHPython
fuente
4

En mi caso tuve que agregar FormsModuley ReactiveFormsModuleal shared.module.tstambién:

(gracias a @Undrium por el ejemplo de código ):

import { NgModule }                                 from '@angular/core';
import { CommonModule }                             from '@angular/common';
import { FormsModule, ReactiveFormsModule }         from '@angular/forms';

@NgModule({
  imports:      [
    CommonModule,
    ReactiveFormsModule
  ],
  declarations: [],
  exports: [
    CommonModule,
    FormsModule,
    ReactiveFormsModule
  ]
})
export class SharedModule { }
Puñal
fuente
Esto resolvió mi problema. Agregarlo solo a app.module no fue suficiente
emirhosseini
3

Tuve este problema y me di cuenta de que no había vinculado mi componente a una variable.

Cambiado

<input #myComponent="ngModel" />

a

<input #myComponent="ngModel" [(ngModel)]="myvar" />

Birwin
fuente
2

La forma correcta de usar formularios ahora en Angular2 es:

<form  (ngSubmit)="onSubmit()">

        <label>Username:</label>
        <input type="text" class="form-control"   [(ngModel)]="user.username" name="username" #username="ngModel" required />

        <label>Contraseña:</label>
        <input type="password" class="form-control"  [(ngModel)]="user.password" name="password" #password="ngModel" required />


    <input type="submit" value="Entrar" class="btn btn-primary"/>

</form>

La forma antigua ya no funciona

ioses
fuente
1

También me di cuenta de que este problema surge cuando se intenta combinar enfoques de formulario reactivo y formulario de plantilla. Tenía #name="ngModel"y [formControl]="name"en el mismo elemento. Eliminar cualquiera de los dos solucionó el problema. Tampoco es que si lo usa #name=ngModeltambién debería tener una propiedad como esta [(ngModel)]="name", de lo contrario, aún obtendrá los errores. Esto también se aplica a los angulares 6, 7 y 8.

Samuel Mutemi
fuente
0

Compruebe que tiene ambos ngModel and nameatributos en su selección. También Select es un componente de formulario y no el formulario completo, por lo que una declaración más lógica de referencia local será: -

<div class="form-group">
    <label for="actionType">Action Type</label>
    <select
            ngControl="actionType" 
      ===>  #actionType="ngModel"
            ngModel    // You can go with 1 or 2 way binding as well
            name="actionType"
            id="actionType" 
            class="form-control" 
            required>
            <option value=""></option>
            <option *ngFor="let actionType of actionTypes" value="{{ actionType.label }}">
                {{ actionType.label }}
            </option>
        </select> 
    </div>

Una cosa más importante es asegurarse de importar, ya sea FormsModuleen el caso del enfoque basado en plantillas o ReactiveFormsModuleen el caso del enfoque reactivo. O puede importar ambos, lo que también está totalmente bien.

Rohan Shenoy
fuente
0

si ngModuleno funciona en la entrada significa intentar ... eliminar las comillas dobles alrededorngModule

me gusta

<input #form="ngModel" [(ngModel)]......></input>

en lugar de arriba

<input #form=ngModel [(ngModel)]......></input> try this
usuario13482587
fuente
-1

Tuve este problema porque tenía un error tipográfico en mi plantilla cerca de [(ngModel)]]. Soporte adicional. Ejemplo:

<input id="descr" name="descr" type="text" required class="form-control width-half"
      [ngClass]="{'is-invalid': descr.dirty && !descr.valid}" maxlength="16" [(ngModel)]]="category.descr"
      [disabled]="isDescrReadOnly" #descr="ngModel">
Raman Zhylich
fuente