首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >ngDefaultControl在角度上是什么?

ngDefaultControl在角度上是什么?
EN

Stack Overflow用户
提问于 2017-09-28 09:41:08
回答 1查看 81.9K关注 0票数 196

不,这不是重复的问题。你看,在SO和Github中有很多问题和问题,它们规定我应该将这个指令添加到一个带有[(ngModel)]指令的标记中,而不是包含在一个表单中。如果我不加它,我会得到一个错误:

代码语言:javascript
运行
复制
ERROR Error: No value accessor for form control with unspecified name attribute

好的,如果我把这个属性放在那里,错误就会消失。但是等等!没人知道它是干什么的!而格朗的医生根本没提过。当我知道我不需要它时,为什么我需要一个值访问器?这个属性是如何连接到值访问器的?这个指令是做什么的?什么是值访问器,我如何使用它?

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

然后。我阅读的不是一本,而是两本关于角形的巨大指南和一节关于ngModel的文章。

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

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-09-28 09:44:07

ngDefaultControl

第三方控件要求ControlValueAccessor具有角形式的功能。它们中的许多,如聚合物的<paper-input>,行为像<input>本机元素,因此可以使用DefaultValueAccessor。添加一个ngDefaultControl属性将允许他们使用该指令。

代码语言:javascript
运行
复制
<paper-input ngDefaultControl [(ngModel)]="value>

代码语言:javascript
运行
复制
<paper-input ngDefaultControl formControlName="name">

这就是为什么这个阿特鲁布特被引入的主要原因。

它被称为ng-default-control属性在angular2的alpha版本中

因此,ngDefaultControlDefaultValueAccessor指令的选择器之一:

代码语言:javascript
运行
复制
@Directive({
  selector:
      'input:not([type=checkbox])[formControlName],
       textarea[formControlName],
       input:not([type=checkbox])[formControl],
       textarea[formControl],
       input:not([type=checkbox])[ngModel],
       textarea[ngModel],
       [ngDefaultControl]', <------------------------------- this selector
  ...
})
export class DefaultValueAccessor implements ControlValueAccessor {

这是什么意思?

这意味着我们可以将这个属性应用于没有自己的值访问器的元素(如聚合物组分)。因此,这个元素将从DefaultValueAccessor的行为,我们可以使用这个元素的角度形式。

否则,您必须提供自己的ControlValueAccessor实现。

ControlValueAccessor

docs状态

ControlValueAccessor充当角度窗体API和DOM中的本机元素之间的桥梁。

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

代码语言:javascript
运行
复制
<input type="text" [(ngModel)]="userName">

为了了解上面的input的行为,我们需要知道应用到这个元素的是哪些指令。在这里,角给出了一些提示与错误:

未处理的承诺拒绝:模板解析错误:无法绑定到“ngModel”,因为它不是“输入”的已知属性。

好的,我们可以打开它并得到答案:将FormsModule导入您的@NgModule

代码语言:javascript
运行
复制
@NgModule({
  imports: [
    ...,
    FormsModule
  ]
})
export AppModule {}

我们导入了它,所有的工作都是按预期进行的。但引擎盖下面是怎么回事?

FormsModule为我们导出以下指令:

代码语言:javascript
运行
复制
@NgModule({
 ...
  exports: [InternalFormsSharedModule, TEMPLATE_DRIVEN_DIRECTIVES]
})
export class FormsModule {}

经过一些调查,我们可以发现三个指令将应用于我们的input

1) NgControlStatus

代码语言:javascript
运行
复制
@Directive({
  selector: '[formControlName],[ngModel],[formControl]',
  ...
})
export class NgControlStatus extends AbstractControlStatus {
  ...
}

2) NgModel

代码语言:javascript
运行
复制
@Directive({
  selector: '[ngModel]:not([formControlName]):not([formControl])',
  providers: [formControlBinding],
  exportAs: 'ngModel'
})
export class NgModel extends NgControl implements OnChanges, 

3) DEFAULT_VALUE_ACCESSOR

代码语言:javascript
运行
复制
@Directive({
  selector:
      `input:not([type=checkbox])[formControlName],
       textarea[formControlName],
       input:not([type=checkbox])formControl],
       textarea[formControl],
       input:not([type=checkbox])[ngModel],
       textarea[ngModel],[ngDefaultControl]',
  ,,,
})
export class DefaultValueAccessor implements ControlValueAccessor {

NgControlStatus指令只操作ng-validng-touchedng-dirty等类,我们可以在这里省略它。

DefaultValueAccesstor在提供程序数组中提供NG_VALUE_ACCESSOR令牌:

代码语言:javascript
运行
复制
export const DEFAULT_VALUE_ACCESSOR: any = {
  provide: NG_VALUE_ACCESSOR,
  useExisting: forwardRef(() => DefaultValueAccessor),
  multi: true
};
...
@Directive({
  ...
  providers: [DEFAULT_VALUE_ACCESSOR]
})
export class DefaultValueAccessor implements ControlValueAccessor {

NgModel指令注入在同一个主机元素上声明的构造函数NG_VALUE_ACCESSOR令牌。

代码语言:javascript
运行
复制
export NgModel extends NgControl implements OnChanges, OnDestroy {
 constructor(...
  @Optional() @Self() @Inject(NG_VALUE_ACCESSOR) valueAccessors: ControlValueAccessor[]) {

在我们的例子中,NgModel将注入DefaultValueAccessor。现在,NgModel指令调用共享setUpControl函数:

代码语言:javascript
运行
复制
export function setUpControl(control: FormControl, dir: NgControl): void {
  if (!control) _throwError(dir, 'Cannot find control with');
  if (!dir.valueAccessor) _throwError(dir, 'No value accessor for form control with');

  control.validator = Validators.compose([control.validator !, dir.validator]);
  control.asyncValidator = Validators.composeAsync([control.asyncValidator !, dir.asyncValidator]);
  dir.valueAccessor !.writeValue(control.value);

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

  ...
}

function setUpViewChangePipeline(control: FormControl, dir: NgControl): void 
{
  dir.valueAccessor !.registerOnChange((newValue: any) => {
    control._pendingValue = newValue;
    control._pendingDirty = true;

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

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

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

这是起作用的桥梁:

NgModel设置控件(1)并调用dir.valueAccessor !.registerOnChange方法。ControlValueAccessor将回调存储在ControlValueAccessor属性中,并在input事件发生(3)时触发此回调。最后,在回调内部调用updateControl函数(4)

代码语言:javascript
运行
复制
function updateControl(control: FormControl, dir: NgControl): void {
  dir.viewToModelUpdate(control._pendingValue);
  if (control._pendingDirty) control.markAsDirty();
  control.setValue(control._pendingValue, {emitModelToViewChange: false});
}

其中角调用形成API control.setValue

这是它工作原理的一个简短版本。

票数 314
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46465891

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档