当前位置: 首页 > 知识库问答 >
问题:

什么是角ngDefaultControl?

宋烨烁
2023-03-14

不,这不是一个重复的问题。你看,SO和Github中有大量的问题和问题,规定我将此指令添加到具有[(ngModel)]指令且未包含在表单中的标记中。如果我不添加它,我会得到一个错误:

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

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

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

然后呢。我读了不是一个而是两个关于Angular表单的大型指南和一个关于ngModel的部分:

  • https://angular.io/guide/forms
  • https://angular.io/guide/reactive-forms
  • https://angular.io/guide/template-syntax#ngModel

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

共有1个答案

郜彦
2023-03-14

第三方控件需要ControlValueAccessor才能与角度窗体一起工作。其中很多,比如聚合物的

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

<paper-input ngDefaultControl formControlName="name">

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

在angular2的alpha版本中,它被称为ng默认控件属性。

所以ngDefaultControl是DefaultValueAccess指令的选择器之一:

@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中的行为,我们可以将该元素与角度形式结合使用。

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

角态

ControlValueAccessor充当Angular forms API和DOM中本机元素之间的桥梁。

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

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

为了理解我们上面的输入的行为,我们需要知道哪些指令应用于这个元素。这里角给出了一些错误的提示:

未处理的promise拒绝:模板分析错误:无法绑定到“ngModel”,因为它不是“input”的已知属性。

好的,我们可以打开SO并得到答案:将表单模块导入到您的@NgModule

@NgModule({
  imports: [
    ...,
    FormsModule
  ]
})
export AppModule {}

我们导入了它,所有的工作都如期进行。但是引擎盖下面发生了什么?

为我们导出以下指令:

@NgModule({
 ...
  exports: [InternalFormsSharedModule, TEMPLATE_DRIVEN_DIRECTIVES]
})
export class FormsModule {}

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

1) NgControlStatus

@Directive({
  selector: '[formControlName],[ngModel],[formControl]',
  ...
})
export class NgControlStatus extends AbstractControlStatus {
  ...
}

2) NgModel

@Directive({
  selector: '[ngModel]:not([formControlName]):not([formControl])',
  providers: [formControlBinding],
  exportAs: 'ngModel'
})
export class NgModel extends NgControl implements OnChanges, 

DEFAULT_VALUE_ACCESSOR

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

NgControlState指令只是操作类,如ng-有效ng-触摸ng-脏,我们可以在这里省略它。

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

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\u值\u访问器令牌注入。

export NgModel extends NgControl implements OnChanges, OnDestroy {
 constructor(...
  @Optional() @Self() @Inject(NG_VALUE_ACCESSOR) valueAccessors: ControlValueAccessor[]) {

在本例中,NgModel将注入DefaultValueAccessor。现在NgModel指令调用sharedsetUpControl函数:

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!。注册表更改方法ControlValueAccessor将回调存储在onChange(2)属性中,并在input事件发生时触发此回调(3)。最后,在回调函数(4)中调用updateControl函数

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

其中角度调用形成API控件。设置值

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

 类似资料:
  • 角色决定了员工的管理范围、功能权限,一个员工可以有多个角色。当员工拥有多个角色时,其管理范围、功能权限为多个角色相加。 管理范围 您可设置角色的管理范围,若设置该角色管理范围为部门,则可管理员工与单据;和设置该员工管理范围为项目,则可管理单据。部门支持选择所有部门、所在的部门及所有子部门、指定部门 项目支持选择所有项目、所在的项目及所有子项目、指定项目 功能权限 您可设置角色的功能权限,其中单据、

  • 问题内容: 我最近正在浏览量角器API,并注意到该方法: 调度命令以在webdriver的控制流上下文中执行自定义功能。 我想将此功能添加到我的工具箱中,但是我不确定我完全了解何时可以在实践中使用它,以及它涵盖哪些用例? 问题答案: 量角器的工作方式是有一个内部队列,在其中设置函数的顺序。因此,如果您要在测试中的某个地方调用某个函数而不告诉量角器,则该函数将不在队列中,并且该函数的实际执行可能随时

  • 问题内容: 我见过很多次有人建议使用它: 但是我不明白为什么我们需要它? 问题答案: 一个简单的答案是,它使量角器不必等待Angular承诺,例如来自或解决的Angular承诺,如果您在或期间(例如,“正在加载”消息)测试行为或测试非Angular承诺,角度站点或页面,例如单独的登录页面。 例如,要测试在请求期间设置加载消息的按钮,可以在获取元素时将其设置为+检查其内容 一个更复杂的答案是将其设置

  • 问题内容: 我只是通过例子去一个角和的OpenLayers指令 HERE 和整个下面的例子来: 该示例可以在 此处 视为实时示例。 我的问题是关于正在加载的文件,我不太明白为什么要加载以下脚本: 上面脚本的目的是什么? 编辑:: 我的角度发现了混帐回购协议和文档这里该模块 的位置 。,但我仍然不了解该脚本的用途,文档甚至没有一个示例。 我已经在jQuery中进行了相当多的编码,因此有人可以用jQu

  • 下拉列表包含和包含可见的: 我无法使用此代码: 我没有下拉列表的值。 在这种情况下,下拉列表的量角器代码应该是什么?

  • 问题内容: 我正在看有角度的1.2源代码,我很好奇为什么某些函数以两个美元符号开头。这是某种约定吗? 问题答案: 单个,用于保留公共标识符 保留 专用 标识符的双精度 引用文档: $前缀命名约定 … 如果您检查范围,您可能还会注意到一些以$$开头的属性。这些属性被认为是私有的,不应访问或修改。