angular2 rc.5自定义输入,无值访问器,用于具有未指定名称的表单控制


80

我有这样简单的自定义输入组件,

import {Component, Provider, forwardRef} from "@angular/core";
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from "@angular/forms";

const noop = () => {};

const CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR: any = {
  provide: NG_VALUE_ACCESSOR,
  useExisting: forwardRef(() => CustomInputComponent),
  multi: true
};

@Component({
  selector: 'custom-input',
  template: `

          <input class="form-control" 
                 [(ngModel)]="value" name="somename"
                 (blur)="onTouched()">

  `,
  providers: [CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR]
})
export class CustomInputComponent implements ControlValueAccessor{

  //The internal data model
  private _value: any = '';

  //Placeholders for the callbacks
  private _onTouchedCallback: () => void = noop;

  private _onChangeCallback: (_:any) => void = noop;

  //get accessor
  get value(): any { return this._value; };

  //set accessor including call the onchange callback
  set value(v: any) {
    if (v !== this._value) {
      this._value = v;
      this._onChangeCallback(v);
    }
  }

  //Set touched on blur
  onTouched(){
    this._onTouchedCallback();
  }

  //From ControlValueAccessor interface
  writeValue(value: any) {
    this._value = value;
  }

  //From ControlValueAccessor interface
  registerOnChange(fn: any) {
    this._onChangeCallback = fn;
  }

  //From ControlValueAccessor interface
  registerOnTouched(fn: any) {
    this._onTouchedCallback = fn;
  }

}

我有这样的应用程序模块,

/**
 * Created by amare on 8/15/16.
 */
import { NgModule }                     from '@angular/core';
import { BrowserModule }                from '@angular/platform-browser';
import { ReactiveFormsModule, FormsModule }          from '@angular/forms';
import { AppComponent }                 from './app/app.component';
import {CustomInputComponent} from "./app/shared/custom.input.component";
import {RouterModule} from "@angular/router";
@NgModule({
  imports: [ BrowserModule, ReactiveFormsModule, FormsModule, RouterModule ],
  declarations: [ AppComponent, CustomInputComponent],
  bootstrap: [ AppComponent ]
})
export class AppModule {  
}

和主要

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule }              from './app.module';

platformBrowserDynamic().bootstrapModule(AppModule);

并且我在一个组件中使用了自定义输入,如下所示,但是却收到“没有用于未指定名称属性的表单控件的无值访问器”。

<custom-input name="firstName" [(ngModel)]="firstName"></custom-input>

而app.component看起来像这样

import { Component } from '@angular/core';

@Component({
  moduleId: module.id,
  selector: 'app-root',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.css']
})
export class AppComponent {
  title = 'app works!';

  firstName: string;
}

我对实现ControlValueAccessor的自定义指令有相同的问题。它在RC4中正常工作,但与RC5时出现相同的错误。希望有人能解决。
user2444499 '16

38
尝试添加ngDefaultControl到您的控件中,如下所示:<custom-input name="firstName" [(ngModel)]="firstName" ngDefaultControl></custom-input>
danieleds'Aug

@danieleds非常感谢,即使有角度的团队没有回应,它也像一种魅力。
阿马雷

1
当心您可能正在使用的任何第三方软件包-如果您导入使用旧软件包的任何东西,FORM_DIRECTIVES它将破坏您的应用程序!举个
皮特

对于我之前加入ngDefaultControl [(ngModel)] = “......”工作
themightysapien

Answers:


73

将ngDefaultControl添加到主机中的自定义输入组件中解决了该问题,谢谢@danieleds


8
此解决方案对我不起作用。我有一个名称应用到我的名字input,我也尝试添加ngDefaultControl到输入中,但没有用。还是给了我同样的错误。在RC5
prolink007

2
同意,我在html和ngDefaultControl中添加了name属性,并且我使用了formControl,但它不起作用。
史蒂夫·K

1
查看有关ngDefaultControl工作原理的很好解释-stackoverflow.com/a/46465959/968003。本质上,它添加了default ControlValueAccessor,它充当Angular表单API和DOM中的本机元素之间的桥梁。
亚历克斯·克劳斯

46

将ngDefaultControl添加到自定义输入组件。这增加了双向数据绑定,除非您执行独特的操作,否则不必实现值访问器方法。

<custom-input name="firstName" [(ngModel)]="firstName" ngDefaultControl></custom-input>

12

添加ngDefaultControl到您的输入。例如

<inline-editor type="textarea" [(ngModel)]="editableTextArea" (onSave)="saveEditable($event)" value="valor" ngDefaultControl> </inline-editor> 

然后import { FORM_DIRECTIVES } from '@angular/common';

最后指令: [FORM_DIRECTIVES]

这将起作用:)感谢以上评论


2
请使用反引号和其他markdown命令使您的帖子更具可读性。
buhtz

4
我正在使用RC6,但没有FORM_DIRECTIVES使用@angular/common
Kosmonaft

6
NG2决赛不再需要表格指令
Steve K


0

在出现这种情况的另一种情况下,我[(ngModel)]指定了一个自定义组件,该组件最近进行了重新构建和简化,并且该组件的新版本只是ngModel作为带有emits的普通输入变量使用。

这还不够-输入变量必须重命名为之外的其他名称ngModel,否则组件必须实现ControlValueAccessor接口(有关详细信息,请参阅文档)。一旦一个完成,您将不再收到此错误。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.