【问题标题】:ngModel: No value accessor for ''ngModel:''没有值访问器
【发布时间】:2016-04-02 11:30:29
【问题描述】:

我在 Angular 2.0 (<my-select>) 中创建了一个自定义元素,当我在组件中包含 ngModel 属性时,我立即遇到以下错误:

EXCEPTION: No value accessor for '' in [myModel in App@0:195]

这是一个笨蛋:http://plnkr.co/edit/wlkPWcB92YZASCwCnmcw?p=preview

(打开控制台查看错误)

如果您只是从src/app.ts 中注释掉以下行,组件将正确呈现:

'[ngModel]="myModel"'

我做了以下事情:

  1. 'angular2/common'导入{FORM_DIRECTIVES}
  2. @Componentdirectives 部分中包含FORM_DIRECTIVES
  3. 初始化myModel

我在这里错过了什么?

【问题讨论】:

  • @thierry 说了什么。也不再需要添加 FORM_DIRECTIVES,因为它们默认包含在内。另一个提示,要在打字稿中制作多行字符串,您可以使用反引号 `。这样你就不需要连接字符串
  • @PierreDuc 谢谢,看看我对 thierry 的评论。此外,我使用 WebStorm 并且在使用反引号时语法突出显示很糟糕。需要更新编辑器,但我确实喜欢这种速记方式。
  • 如果您在谈论背景颜色。设置 -> 编辑器 -> 颜色和字体 -> 常规 -> 注入语言片段 -> 取消选中背景颜色。
  • @PierreDuc 就是这样!谢谢!

标签: angular


【解决方案1】:

我接受此错误的原因有 2

1) 组件必须将自己附加为值访问器,例如:

@Component({
  selector: 'ace-editor',
  template: `<div class="ng2-ace-editor"></div>`,
})

export class AceEditor implements OnInit, ControlValueAccessor {

  constructor(private element: ElementRef, @Optional() ngControl: NgControl) {
    if (ngControl) {
      ngControl.valueAccessor = this;
    }
  }

2)您不必混合使用已弃用的表单和新表单。如果您使用新的 API,请添加到您的 main.ts

import { bootstrap }    from '@angular/platform-browser-dynamic';
import { disableDeprecatedForms, provideForms } from '@angular/forms';

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

bootstrap(AppComponent, [
  disableDeprecatedForms(),
  provideForms()
])
.catch((err: any) => console.error(err));

【讨论】:

  • 我错过了ngControl.valueAccessor = this;。您是否有将valueAccessor 设置为this 的文档链接,或者知道您是如何发现它的?我见过的文档或示例都没有提到它。发送
  • 你是对的。没有很好的例子。我不得不使用 Angular 的资源。试试看测试:github.com/angular/angular/blob/…
  • 除了设置valueAccessor = this之外,您还可以使用与this answer不同的方式注册提供者
【解决方案2】:

我认为您应该使用 ngModel 以外的其他参数作为 my-select 组件的参数...因为 Angular2 已经使用了它。

我尝试了model,它似乎更好......我不再有错误了。

编辑

如果您想在 my-select 组件级别处理 ngModel,您可以查看此链接:https://github.com/angular/angular/issues/2543

如果您想实现符合 ngModel 的组件,可以查看以下链接:

希望对你有帮助 蒂埃里

【讨论】:

  • 我们不允许使用ngModel?如果是这样,我很困惑为什么它被包含在备忘单的Forms 部分(angular.io/cheatsheet)(即&lt;input [(ngModel)]="userName"&gt;)。也就是说,如果我不使用它,我可以确认问题已解决,但错误说明是什么?
  • 如果我没记错的话,ngModel 需要一个 Control 实例
  • 我错了……我不知道……忽略我,我把ngModelngControl 混淆了。 documentation 所说的唯一内容是“将域模型绑定到表单控件”。但是通过判断您的错误,我希望它只能绑定到具有value 属性(输入、文本区域、选择)的 html 标记
  • 我认为您需要管理组件的输入/输出。我用一个可能有用的链接更新了我的答案...
  • 这个问题解决了吗?与 beta.1 有同样的问题
【解决方案3】:

我遇到了同样的问题。我想我尝试将我的变量双向绑定到 &lt;span&gt; 元素,然后在属性中获取该值:

<span [(ngModel)]="_hidden" [hidden]="_hidden" class="field-validation-error">Username is required.</span>

如您所见,视图无法修改模型中的_hidden 变量。将绑定修复为单向有效:

&lt;span (ngModel)="_hidden" [hidden]="_hidden" class="field-validation-error"&gt;Username is required.&lt;/span&gt;

注意从 [(ngModel)](ngModel) 的变化。

【讨论】:

  • 为什么还要在&lt;span&gt; 上使用ngModel?用例是什么?
  • 在我的项目中:登录表单。当用户未提供用户名或密码并单击提交按钮时,&lt;input type="text"&gt; 旁边应显示消息“X is required”。
  • &lt;span&gt;{{username}} is required&lt;/span&gt;ngModel 用于输入元素。普通文本绑定不需要使用它。
  • 我很确定 &lt;span [hidden]="_hidden" class="field-validation-error"&gt;Username is required.&lt;/span&gt; 的作用完全一样。
  • 哦,它确实有效,我明白了。每天更聪明,谢谢!
【解决方案4】:

试试这个

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

从 @angular/forms 导入任何和所有表单符号 - NgForm、验证器等。从 @angular/common 导入它们会导致 No value accessor found 错误。

【讨论】:

  • 注意:这在 Angular 2 的最终发行版中不起作用。
【解决方案5】:

就我而言,这是一个简单的拼写错误。组件的选择器是“my-component”,但在 html 中我输入了&lt;my-compoent&gt;。注意到最后三个字母了吗?编译得很好,然后在运行时出现“无值访问器”错误。

根据我的经验,由于这里和那里的拼写错误,您可能会遇到一些其他非常奇怪的错误。 Typescript 编译器不关心标记。

【讨论】:

  • 哇,伙计...我只是因为一个错字而丢掉了一天的最后 2 个小时。愤怒。感谢您的洞察力
【解决方案6】:

我在 gulp 中创建发布任务时遇到了类似的问题。我使用您在 plunker 中使用的 Angular2 代码的缩小版本将其追踪到错误。 github 上的 Angular2 Issue 是我找到答案的地方,这里是 Igor Minar 对 the Issue 的回复(Igor 是 Angular2 项目的主要贡献者)。

TL;DR; 使用 .dev Angular2 库文件,直到 Angular 团队解决此问题。

【讨论】:

    【解决方案7】:

    我没有使用新的表单 API,在我的单元测试中我仍然收到 NgModel 的此错误。

    看起来仅仅在你的组件中指定NgModel 是不够的。例如

    之前
    directives:[NgModel]

    之后
    directives:[FORM_DIRECTIVES]

    这解决了我的问题。 干杯:)

    【讨论】:

      【解决方案8】:

      @DenisKolodin's answer 提到使用ngControl.valueAccessor = this; 设置访问器。但是,some articles 建议以这种方式注册提供程序:

      @Component({
        selector: '...',
        template: '...',
        providers: [
        {
          provide: NG_VALUE_ACCESSOR,
          useExisting: forwardRef(() => MyComponent ),
          multi: true,
        }      
      })
      export class MyComponent implements ControlValueAccessor{ ...
      

      这就是Angular's DefaultValueAccessor source中的做法

      【讨论】:

        【解决方案9】:

        我也遇到了这个错误。这是我的愚蠢。我会在这里描述它以防其他人跳进去。

        用于在组件之间传递变量的 2 路绑定格式(假设我想将名为 myObj 的 obj 从组件 A 传递到组件 B)。

        所以在组件 A 的模板中我会有类似的东西

        <componentB [(myObjectInB)]="myObjectInA"></componentB>
        

        在组件 B 中,我必须有一个名为 myObjectInB 的对象,我们声明它的方式必须是:

        @Input() myObjectInB ...
        

        这里的 @Input() 是我错过的,所以这就是它抛出该错误的原因。

        【讨论】:

          【解决方案10】:

          >=RC.5

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

          FormsModule 和/或 ReativeFormsModule 取决于您是使用模板驱动表单、模型驱动表单还是两者兼而有之

          另见

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2016-11-04
            • 2017-04-25
            • 1970-01-01
            • 2018-01-21
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多