Erro Angular2: Não há diretiva com “exportAs” definido como “ngForm”

109

Estou no RC4 e estou recebendo o erro Não há diretiva com "exportAs" definida como "ngForm" por causa do meu modelo:

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

o 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]);

/// então aqui está a minha 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>

// meu componente ts:

eu estava representando nas formas antigas, assim:

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

e agora estou fazendo isso:

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

você acha que é a causa do problema ??

Anna
fonte
Qual versão você está usando? Você reforçou os formulários?
acdcjunior

Respostas:

98

Desde 2.0.0.rc6 :

formulários : obsoleto provideForms()e as disableDeprecatedForms()funções foram removidas. Em vez disso, importe FormsModuleou ReactiveFormsModulede @angular/forms.

Em resumo:

Portanto, adicione ao seuapp.module.ts ou 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 { }

Não ter um desses módulos pode levar a erros, incluindo o que você enfrenta:

Não é possível vincular a 'ngModel', pois não é uma propriedade conhecida de 'input'.

Não é possível vincular a 'formGroup', pois não é uma propriedade conhecida de 'form'

Não há diretiva com "exportAs" definido como "ngForm"

Se você estiver em dúvida, pode fornecer o FormsModulee o ReactiveFormsModulejuntos, mas eles funcionam totalmente separadamente. Quando você fornece um desses módulos, as diretivas de formulários padrão e provedores desse módulo estarão disponíveis para todo o aplicativo.


Formulários antigos usando ngControl?

Se você tiver esses módulos @NgModule, talvez esteja usando diretivas antigas, como ngControl, o que é um problema, porque não há ngControlnos novos formulários. Foi substituído mais ou menos * por ngModel.

Por exemplo, o equivalente a <input ngControl="actionType">é <input ngModel name="actionType">, então mude isso em seu modelo.

Da mesma forma, a exportação em controles não é ngFormmais, é agora ngModel. Portanto, no seu caso, substitua #actionType="ngForm"por #actionType="ngModel".

Portanto, o modelo resultante deve ser ( ===>onde alterado):

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

* Mais ou menos porque nem todas as funcionalidades do ngControlforam movidas para ngModel. Alguns apenas foram removidos ou estão diferentes agora. Um exemplo é o nameatributo, o próprio caso que você está tendo agora.

acdcjunior
fonte
obrigado pela sua resposta, quando eu mudei, estou tendo o erro Não é possível atribuir a uma referência ou variável isso diz algo para você ??
Anna
Hmm .. pode estar em outro lugar. Você tem algum <input>dentro de um *ngFor? (Provavelmente não vai funcionar, mas tentar isso e me dizer se a mensagem vai embora: <option *ngFor="let actionType of actionTypes; let i = index" value="{{ actionTypes[i].label }}"> {{ actionTypes[i].label }} </option>)
acdcjunior
Você tem algum <input> dentro de um *ngFor?
acdcjunior
Tente renomear a variável dentro do *ngFor para algo diferente de actionType, algum bom?
acdcjunior
Não, não, mas tenho uma lista suspensa selecionada que estou iterando, não sei se é a origem do erro, dê uma olhada na minha pergunta atualizada ...
Anna
61

Eu enfrentei o mesmo problema. Eu tinha perdido a tag de importação do módulo de formulários no app.module.ts

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

@NgModule({
    imports: [BrowserModule,
        FormsModule
    ],
Chandan
fonte
2
obrigado por isso, funcionou bem, mas deveria ser app.module.ts e não app.module.component.ts
Salim
Isso não está funcionando para mim, embora eu já tenha colocado a importação do FormsModule em meu app.module
emirhosseini
9

Tive o mesmo problema que foi resolvido adicionando o FormsModule ao .spec.ts:

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

e, em seguida, adicionar a importação a beforeEach:

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

Se você estiver recebendo isto:

Erro: erros de análise de modelo:

Não há nenhuma diretiva com "exportAs" definido como " ngModel "

Que foi relatado como um bug no github , então provavelmente não é um bug, pois você pode:

  1. tem um erro de sintaxe (por exemplo, um colchete extra:) [(ngModel)]]=, OU
  2. estar misturando diretivas de formas reativas , como, por exemplo formControlName, com a ngModeldiretiva . Este "foi descontinuado no Angular v6 e será removido no Angular v7" , pois combina as duas estratégias de formulário, tornando-o:
  • parece que a ngModeldiretiva real está sendo usada, mas na verdade é uma propriedade de entrada / saída nomeada ngModelna diretiva de formulário reativo que simplesmente aproxima (parte) de seu comportamento. Especificamente, permite obter / definir o valor e interceptar eventos de valor. No entanto, alguns dos ngModeloutros recursos do - como atrasar as atualizações com ngModelOpções ou exportar a diretiva - simplesmente não funcionam (...)

  • esse padrão mistura estratégias de formulários orientados a modelos e reativos, que geralmente não recomendamos porque não tira proveito de todos os benefícios de nenhuma das estratégias . (...)

  • Para atualizar seu código antes da v7, você desejará decidir se deseja manter as diretivas de formulários reativos (e obter / definir valores usando padrões de formulários reativos) ou mudar para diretivas orientadas a modelos .

Quando você tem uma entrada como esta:

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

Ele mostrará um aviso sobre estratégias de formulários mistos no console do navegador:

Parece que você está usando ngModelno mesmo campo de formulário que formControlName.

No entanto, se você adicionar o ngModelcomo um valor em uma variável de referência, exemplo:

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

O erro acima é então acionado e nenhum aviso sobre combinação de estratégias é mostrado.

CPHPython
fonte
4

No meu caso eu tive que adicionar FormsModulee ReactiveFormsModuleao shared.module.tsdemais:

(obrigado a @Undrium pelo exemplo 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 { }
Dirk
fonte
Isso resolveu meu problema. Adicioná-lo apenas ao app.module não foi suficiente
emirhosseini
3

Tive esse problema e percebi que não havia vinculado meu componente a uma variável.

Alterado

<input #myComponent="ngModel" />

para

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

Birwin
fonte
2

A maneira correta de usar formulários agora no Angular2 é:

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

O jeito antigo não funciona mais

Ioses
fonte
1

Também percebi que esse problema surge ao tentar combinar abordagens de formulário reativo e modelo de formulário. Eu tinha #name="ngModel"e [formControl]="name"no mesmo elemento. Remover qualquer um corrigiu o problema. Também não que se você usar, #name=ngModelvocê também deve ter uma propriedade como esta [(ngModel)]="name", caso contrário, você ainda obterá os erros. Isso se aplica ao angular 6, 7 e 8 também.

Samuel Mutemi
fonte
0

Verifique se você tem ambos os ngModel and nameatributos em sua seleção. Além disso, o Select é um componente do formulário e não todo o formulário, portanto, a declaração mais lógica de referência 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>

Mais uma coisa importante é certificar-se de importar FormsModuleno caso de abordagem orientada por modelo ou ReactiveFormsModuleno caso de abordagem reativa. Ou você pode importar ambos, o que também é totalmente normal.

Rohan Shenoy
fonte
0

se ngModulenão estiver funcionando na entrada significa tentar ... remover aspas duplas ao redorngModule

gostar

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

em vez de acima

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

Eu tive esse problema porque eu tive um erro de digitação em meu modelo próximo a [(ngModel)]]. Suporte extra. Exemplo:

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