118

i'm on the RC4 and i'm getting the error There is no directive with "exportAs" set to "ngForm" because of my template :

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

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

/// so here is my 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>

//my component ts :

i was representing it in the old forms like this :

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

and now i'm doing this :

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

you think it's the cause of the prob ??

risingTide
  • 1,356
  • 7
  • 20
  • 50
Anna
  • 1,537
  • 5
  • 11
  • 15

11 Answers11

106

Since 2.0.0.rc6:

forms: deprecated provideForms() and disableDeprecatedForms() functions have been removed. Please import the FormsModule or the ReactiveFormsModule from @angular/forms instead.

In short:

So, add to your app.module.ts or equivalent:

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

Failing to have one of these modules can lead to errors, including the one you face:

Can't bind to 'ngModel' since it isn't a known property of 'input'.

Can't bind to 'formGroup' since it isn't a known property of 'form'

There is no directive with "exportAs" set to "ngForm"

If you're in doubt, you can provide both the FormsModule and the ReactiveFormsModule together, but they are fully-functional separately. When you provide one of these modules, the default forms directives and providers from that module will be available to you app-wide.


Old Forms using ngControl?

If you do have those modules at your @NgModule, perhaps you are using old directives, such as ngControl, which is a problem, because there's no ngControl in the new forms. It was replaced more or less* by ngModel.

For instance, the equivalent to <input ngControl="actionType"> is <input ngModel name="actionType">, so change that in your template.

Similarly, the export in controls is not ngForm anymore, it is now ngModel. So, in your case, replace #actionType="ngForm" with #actionType="ngModel".

So the resulting template should be (===>s where changed):

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

* More or less because not all functionality of ngControl was moved to ngModel. Some just were removed or are different now. An example is the name attribute, the very case you are having right now.

Community
  • 1
  • 1
acdcjunior
  • 114,460
  • 30
  • 289
  • 276
  • thank's for your answer, when i've change it i'm having the error **Cannot assign to a reference or variable** does it say something to you ?? – Anna Jul 29 '16 at 00:40
  • Hmm.. it may be somewhere else. Do you have any `` inside a `*ngFor`? (Probably won't work but try this and tell me if the message goes away: ``) – acdcjunior Jul 29 '16 at 00:55
  • Do you have any inside a `*ngFor`? – acdcjunior Jul 29 '16 at 01:05
  • Try renaming the variable inside the `*ngFor` to something other than `actionType`, any good? – acdcjunior Jul 29 '16 at 01:05
  • nope i don't but i have a select dropdown list that i'm iterating i don't know if it's the source of the error, please get a look at my updated question ... – Anna Jul 29 '16 at 01:07
  • Shouldn't, inside the `option *ngFor`, the `{{processus.Process.label}}` be `{{processus[i].Process.label}}` (or the contrary, inside the ` – acdcjunior Jul 29 '16 at 01:18
  • the two of them :( – Anna Jul 29 '16 at 01:19
  • About the `{{processus.Process.label}}` or `{{processus[i].Process.label}}`, which one is correct? – acdcjunior Jul 29 '16 at 01:20
  • without the i index, the first one : {{processus.Process.label}} was working pretty well on deprecated forms, and now even after trying your suggestion the error still here – Anna Jul 29 '16 at 01:22
  • `ngControlGroup`, in the new forms, was replaced by `ngModelGroup`, can you change it? – acdcjunior Jul 29 '16 at 01:29
  • Look, your code works here: http://plnkr.co/edit/ztRcGvD0CXnKklpkfH0U?p=preview Can you change it so it is more like yours and fails? – acdcjunior Jul 29 '16 at 01:32
  • i think the error come from my component not the template, i've updated my question to show you the definition : – Anna Jul 29 '16 at 10:56
  • adding the formsModule to my app module worked for me – pepitomb Jun 27 '18 at 22:02
61

I faced the same issue. I had missed the forms module import tag in the app.module.ts

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

@NgModule({
    imports: [BrowserModule,
        FormsModule
    ],
ProllyGeek
  • 14,423
  • 5
  • 44
  • 69
Chandan
  • 1,347
  • 2
  • 12
  • 20
9

I had the same problem which was resolved by adding the FormsModule to the .spec.ts:

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

and then adding the import to beforeEach:

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

If you are getting this instead:

Error: Template parse errors:

There is no directive with "exportAs" set to "ngModel"

Which was reported as a bug in github, then likely it is not a bug since you might:

  1. have a syntax error (e.g. an extra bracket: [(ngModel)]]=), OR
  2. be mixing Reactive forms directives, such as formControlName, with the ngModel directive. This "has been deprecated in Angular v6 and will be removed in Angular v7", since this mixes both form strategies, making it:
  • seem like the actual ngModel directive is being used, but in fact it's an input/output property named ngModel on the reactive form directive that simply approximates (some of) its behavior. Specifically, it allows getting/setting the value and intercepting value events. However, some of ngModel's other features - like delaying updates withngModelOptions or exporting the directive - simply don't work (...)

  • this pattern mixes template-driven and reactive forms strategies, which we generally don't recommend because it doesn't take advantage of the full benefits of either strategy. (...)

  • To update your code before v7, you'll want to decide whether to stick with reactive form directives (and get/set values using reactive forms patterns) or switch over to template-driven directives.

When you have an input like this:

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

It will show a warning about mixed form strategies in the browser's console:

It looks like you're using ngModel on the same form field as formControlName.

However, if you add the ngModel as a value in a reference variable, example:

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

The error above is then triggered and no warning about strategy mixing is shown.

Community
  • 1
  • 1
CPHPython
  • 6,842
  • 2
  • 41
  • 58
4

In my case I had to add FormsModule and ReactiveFormsModule to the shared.module.ts too:

(thanks to @Undrium for the code example):

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
  • 1,871
  • 1
  • 19
  • 25
4

I had this problem and I realized I had not bound my component to a variable.

Changed

<input #myComponent="ngModel" />

to

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

birwin
  • 2,032
  • 2
  • 14
  • 35
3

Also realized this problem comes up when trying to combine reactive form and template form approaches. I had #name="ngModel" and [formControl]="name" on the same element. Removing either one fixed the issue. Also not that if you use #name=ngModel you should also have a property such as this [(ngModel)]="name" , otherwise, You will still get the errors. This applies to angular 6, 7 and 8 too.

Samuel Mutemi
  • 181
  • 1
  • 6
2

The correct way of use forms now in Angular2 is:

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

The old way doesn't works anymore

ioses
  • 937
  • 1
  • 8
  • 11
0

Check that you have both ngModel and name attributes in your select. Also Select is a form component and not the entire form so more logical declaration of local reference will be:-

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

One more Important thing is make sure you import either FormsModule in the case of template driven approach or ReactiveFormsModule in the case of Reactive approach. Or you can import both which is also totally fine.

Rohan Shenoy
  • 607
  • 6
  • 17
0

if ngModule is not working in input means try...remove double quotes around ngModule

like

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

instead of above

<input #form=ngModel [(ngModel)]......></input> try this
Habib
  • 677
  • 2
  • 8
  • 20
-1

I had this problem because I had a typo in my template near [(ngModel)]]. Extra bracket. Example:

<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
  • 3,182
  • 22
  • 22