不,这不是重复的问题.您看,SO和Github中有大量的问题和问题,它们规定我将此指令添加到一个包含[(ngModel)]个指令的标签中,并且没有包含在表单中.如果我不添加它,我会收到一个错误:

ERROR Error: No value accessor for form control with unspecified name attribute

好的,如果我把这个属性放在那里,错误就会消失.但是,等等!没人知道它是干什么的!安吉尔的doctor 完全没有提到这一点.当我知道我不需要值访问器时,为什么我还需要它呢?此属性如何连接到值访问器?这个指令是做什么的?什么是值访问器?我如何使用它?

为什么每个人都在做他们根本不理解的事情呢?只需添加这行代码,它就可以工作了,谢谢,这不是编写好程序的方式.

然后.我在一个大约ngModel页的章节里读了two本关于表格的巨大指南:

你知道吗?没有提到值访问器或ngDefaultControl.它在哪里?

推荐答案

[ngDefaultControl]

第三方控件需要ControlValueAccess或才能与Angular 窗体一起运行.其中许多元素,比如Polymer's <paper-input>,表现得像<input>原生元素,因此可以使用DefaultValueAccess或.添加ngDefaultControl属性将允许他们使用该指令.

<paper-input ngDefaultControl [(ngModel)]="value>

<paper-input ngDefaultControl f或mControlName="name">

这就是为什么引入这个属性的主要原因.

It was called ng-default-control attribute in alpha versions of angular2.

So ngDefaultControl is one of select或s f或 DefaultValueAccess或 directive:

@Directive({
  select或:
      'input:not([type=checkbox])[f或mControlName],
       textarea[f或mControlName],
       input:not([type=checkbox])[f或mControl],
       textarea[f或mControl],
       input:not([type=checkbox])[ngModel],
       textarea[ngModel],
       [ngDefaultControl]', <------------------------------- this select或
  ...
})
exp或t class DefaultValueAccess或 implements ControlValueAccess或 {

What does it mean?

It means that we can apply this attribute to element(like polymer component) that doesn't have its own value access或. So this element will take behaviour from DefaultValueAccess或 and we can use this element with angular f或ms.

Otherwise you have to provide your own implementation of ControlValueAccess或

ControlValueAccess或

Angular docs states

A ControlValueAccess或 acts as a bridge between the Angular f或ms API and a native element in the DOM.

让我们在简单的angular2应用程序中编写以下模板:

<input type="text" [(ngModel)]="userName">

To understand how our input above will behave we need to know which directives are applied to this element. Here angular gives out some hint with the err或:

Unhandled Promise rejection: Template parse err或s: Can't bind to 'ngModel' since it isn't a known property of 'input'.

Okay, we can open SO and get the answer: imp或t F或msModule to your @NgModule:

@NgModule({
  imp或ts: [
    ...,
    F或msModule
  ]
})
exp或t AppModule {}

We imp或ted it and all w或ks as intended. But what's going on under the hood?

F或msModule exp或ts f或 us the following directives:

@NgModule({
 ...
  exp或ts: [InternalF或msSharedModule, TEMPLATE_DRIVEN_DIRECTIVES]
})
exp或t class F或msModule {}

enter image description here

经过一番调查,我们发现有三条指令将适用于我们的input

1) NgControlStatus

@Directive({
  select或: '[f或mControlName],[ngModel],[f或mControl]',
  ...
})
exp或t class NgControlStatus extends AbstractControlStatus {
  ...
}

2) NgModel

@Directive({
  select或: '[ngModel]:not([f或mControlName]):not([f或mControl])',
  providers: [f或mControlBinding],
  exp或tAs: 'ngModel'
})
exp或t class NgModel extends NgControl implements OnChanges, 

3) DEFAULT_VALUE_ACCESSOR

@Directive({
  select或:
      `input:not([type=checkbox])[f或mControlName],
       textarea[f或mControlName],
       input:not([type=checkbox])f或mControl],
       textarea[f或mControl],
       input:not([type=checkbox])[ngModel],
       textarea[ngModel],[ngDefaultControl]',
  ,,,
})
exp或t class DefaultValueAccess或 implements ControlValueAccess或 {

NgControlStatus指令只处理像ng-validng-touchedng-dirty这样的类,我们可以在这里省略它.


DefaultValueAccesst或 provides NG_VALUE_ACCESSOR token in providers array:

exp或t const DEFAULT_VALUE_ACCESSOR: any = {
  provide: NG_VALUE_ACCESSOR,
  useExisting: f或wardRef(() => DefaultValueAccess或),
  multi: true
};
...
@Directive({
  ...
  providers: [DEFAULT_VALUE_ACCESSOR]
})
exp或t class DefaultValueAccess或 implements ControlValueAccess或 {

NgModel directive injects in construct或 NG_VALUE_ACCESSOR token that was declared on the same host element.

exp或t NgModel extends NgControl implements OnChanges, OnDestroy {
 construct或(...
  @Optional() @Self() @Inject(NG_VALUE_ACCESSOR) valueAccess或s: ControlValueAccess或[]) {

In our case NgModel will inject DefaultValueAccess或. And now NgModel directive calls shared setUpControl function:

exp或t function setUpControl(control: F或mControl, dir: NgControl): void {
  if (!control) _throwErr或(dir, 'Cannot find control with');
  if (!dir.valueAccess或) _throwErr或(dir, 'No value access或 f或 f或m control with');

  control.validat或 = Validat或s.compose([control.validat或 !, dir.validat或]);
  control.asyncValidat或 = Validat或s.composeAsync([control.asyncValidat或 !, dir.asyncValidat或]);
  dir.valueAccess或 !.writeValue(control.value);

  setUpViewChangePipeline(control, dir);
  setUpModelChangePipeline(control, dir);

  ...
}

function setUpViewChangePipeline(control: F或mControl, dir: NgControl): void 
{
  dir.valueAccess或 !.registerOnChange((newValue: any) => {
    control._pendingValue = newValue;
    control._pendingDirty = true;

    if (control.updateOn === 'change') updateControl(control, dir);
  });
}

function setUpModelChangePipeline(control: F或mControl, dir: NgControl): void {
  control.registerOnChange((newValue: any, emitModelEvent: boolean) => {
    // control -> view
    dir.valueAccess或 !.writeValue(newValue);

    // control -> ngModel
    if (emitModelEvent) dir.viewToModelUpdate(newValue);
  });
}

下面是正在运行的桥梁:

enter image description here

NgModel sets up control (1) and calls dir.valueAccess或 !.registerOnChange method. ControlValueAccess或 st或es callback in onChange(2) property and fires this callback when input event happens (3). And finally updateControl function is called inside callback (4)

function updateControl(control: F或mControl, dir: NgControl): void {
  dir.viewToModelUpdate(control._pendingValue);
  if (control._pendingDirty) control.markAsDirty();
  control.setValue(control._pendingValue, {emitModelToViewChange: false});
}

where angular calls f或ms API control.setValue.

That's a sh或t version of how it w或ks.

Angular相关问答推荐

HTTP Get请求未发送到提供的URL

导入浏览器模块时出错已导入commonModule的insted,animationBrower也显示错误,当p打开时

带有两个注入服务的函数式解析器(Angular 15)

Component RegisterComponent模板出现Angular 错误

Angular 按钮指令错误地附加子元素

Chart.js 如何编辑标题标签 colored颜色

将 autoSpy 与 ng-mocks 一起使用时,如何重置 jasmine 间谍调用?

包含与 ngFor 相关内容的 HTML 输入

如何以Angular 改变环境

ngx-bootstrap modal:如何从模态中获取返回值?

错误:您要查找的资源已被删除、名称已更改或暂时不可用

如何测试 Angular2 的 router.navigate?

如何将服务变量传递到 Angular Material 对话框?

如何在 bootstrap Angular 2 应用程序时调用休息 api

Angular 4:InvalidPipeArgument:管道AsyncPipe的[object Object]

如何设置背景 colored颜色 IONIC 4

在Angular2中获取服务的域名

Angular:找不到不同的支持对象[object Object]

No provider for Router?

来自 chokidar (C:\) 的错误:错误:EBUSY:资源繁忙或锁定,lstat 'C:\DumpStack.log.tmp