【问题标题】:Angular2 Error: There is no directive with "exportAs" set to "ngForm"Angular2 错误:没有将“exportAs”设置为“ngForm”的指令
【发布时间】:2016-12-03 13:21:24
【问题描述】:

我在 RC4 上,我收到错误 由于我的模板,没有将“exportAs”设置为“ngForm”的指令

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

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

/// 所以这是我的 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>

//我的组件ts:

我用这样的旧形式来表示它:

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

现在我正在这样做:

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

你认为这是问题的原因??

【问题讨论】:

  • 你用的是什么版本?您是否对表单进行了增强?

标签: angular typescript angular2-forms


【解决方案1】:

2.0.0.rc6:

表单:已弃用的 provideForms()disableDeprecatedForms() 函数已被删除。请改为从@angular/forms 导入FormsModuleReactiveFormsModule

简而言之:

所以,添加到您的 app.module.ts 或同等的:

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

没有这些模块之一可能会导致错误,包括您面临的错误:

无法绑定到“ngModel”,因为它不是“输入”的已知属性。

无法绑定到“formGroup”,因为它不是“form”的已知属性

没有将“exportAs”设置为“ngForm”的指令

如果您有疑问,可以将you can provide bothFormsModuleReactiveFormsModule 放在一起,但它们的功能完全独立。当您提供这些模块之一时,该模块中的默认表单指令和提供程序将在您的应用范围内可用。


使用ngControl的旧表单?

如果您的@NgModule 中确实有这些模块,那么您可能正在使用旧指令,例如ngControl,这是一个问题,因为新表单中没有ngControl。它或多或少*被ngModel替换。

例如,&lt;input ngControl="actionType"&gt; 的等效项是 &lt;input ngModel name="actionType"&gt;,因此请在模板中更改它。

同样,控件中的导出不再是ngForm,而是现在ngModel。因此,在您的情况下,将#actionType="ngForm" 替换为#actionType="ngModel"

所以生成的模板应该是(===&gt;s 更改的地方):

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

* 或多或少是因为并非ngControl 的所有功能都已移至ngModel。有些刚刚被删除或现在不同了。一个例子是 name 属性,就是你现在遇到的情况。

【讨论】:

  • 感谢您的回答,当我更改它时,我遇到了错误无法分配给引用或变量它对您说了什么吗??
  • 嗯..它可能在其他地方。 *ngFor 中有 &lt;input&gt; 吗? (可能不起作用,但试试这个并告诉我消息是否消失:&lt;option *ngFor="let actionType of actionTypes; let i = index" value="{{ actionTypes[i].label }}"&gt; {{ actionTypes[i].label }} &lt;/option&gt;
  • *ngFor 中有 吗?
  • 尝试将*ngFor 中的变量重命名为actionType 以外的其他名称,好吗?
  • 不,我没有,但我有一个我正在迭代的选择下拉列表我不知道它是否是错误的根源,请查看我更新的问题...
【解决方案2】:

我遇到了同样的问题。我错过了 app.module.ts 中的表单模块导入标签

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

@NgModule({
    imports: [BrowserModule,
        FormsModule
    ],

【讨论】:

  • 谢谢,它工作得很好,但应该是 app.module.ts 而不是 app.module.component.ts
  • 这对我不起作用,即使我已经将 FormsModule 导入到我的 app.module 中
【解决方案3】:

我遇到了同样的问题,通过将 FormsModule 添加到 .spec.ts 解决了这个问题:

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

然后将导入添加到 beforeEach:

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

【讨论】:

    【解决方案4】:

    如果你得到的是这个:

    错误:模板解析错误:

    没有将“exportAs”设置为“ngModel”的指令

    这是reported as a bug in github,那么它可能不是错误,因为您可能:

    1. 有语法错误(例如,额外的括号:[(ngModel)]]=),或者
    2. 混合响应式表单指令,例如formControlNamengModel 指令。这个"has been deprecated in Angular v6 and will be removed in Angular v7",因为这混合了两种表单策略,所以它:
    • 似乎正在使用实际的ngModel 指令,但实际上它是响应式表单指令上名为ngModel 的输入/输出属性,它只是近似(部分)其行为。具体来说,它允许获取/设置值和拦截值事件。但是,ngModel 的一些其他功能 - 例如使用ngModelOptions 延迟更新或导出指令 - 根本不起作用 (...)

    • 这种模式混合了模板驱动和反应式表单策略,我们通常不推荐,因为它没有充分利用这两种策略的全部优势。 (...)

    • 要在 v7 之前更新您的代码,您需要决定是否坚持使用响应式表单指令(并使用响应式表单模式获取/设置值)或切换到模板-驱动指令

    当你有这样的输入时:

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

    它将在浏览器的控制台中显示有关混合表单策略的警告:

    您似乎在与formControlName 相同的表单字段中使用ngModel

    但是,如果您将ngModel 作为值添加到引用变量中,例如:

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

    然后触发上述错误,并且不会显示有关策略混合的警告。

    【讨论】:

      【解决方案5】:

      在我的情况下,我也必须将 FormsModuleReactiveFormsModule 添加到 shared.module.ts

      (感谢@Undrium 提供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 { }
      

      【讨论】:

      • 这解决了我的问题。仅将其添加到 app.module 是不够的
      【解决方案6】:

      我遇到了这个问题,我意识到我没有将我的组件绑定到变量。

      改变了

      &lt;input #myComponent="ngModel" /&gt;

      &lt;input #myComponent="ngModel" [(ngModel)]="myvar" /&gt;

      【讨论】:

        【解决方案7】:

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

        旧方法不再适用

        【讨论】:

          【解决方案8】:

          在尝试结合反应式表单和模板表单方法时,也意识到会出现这个问题。我在同一个元素上有#name="ngModel"[formControl]="name"。删除任何一个都可以解决问题。也不是说如果你使用 #name=ngModel 你也应该有一个像这样的属性 [(ngModel)]="name" ,否则,你仍然会得到错误。这也适用于角度 6、7 和 8。

          【讨论】:

            【解决方案9】:

            如果ngModule 在输入中不起作用,则尝试...删除ngModule 周围的双引号

            喜欢

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

            而不是上面

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

            【讨论】:

              【解决方案10】:

              检查您的选择中是否同时具有ngModel and name 属性。此外 Select 是一个表单组件,而不是整个表单,因此更合乎逻辑的本地引用声明将是:-

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

              另一件重要的事情是确保在模板驱动方法的情况下导入FormsModule,在响应式方法的情况下导入ReactiveFormsModule。或者您可以同时导入两者,这也完全没问题。

              【讨论】:

                【解决方案11】:

                我遇到了这个问题,因为我在 [(ngModel)]] 附近的模板中有错字。额外的支架。示例:

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

                【讨论】:

                  猜你喜欢
                  • 2017-11-08
                  • 2018-01-16
                  • 2018-11-20
                  • 2018-08-05
                  • 2017-09-10
                  • 2018-05-12
                  • 2017-01-26
                  • 2018-10-20
                  相关资源
                  最近更新 更多