不,这不是一个重复的问题。你看,SO和Github中有大量的问题和问题,规定我将此指令添加到具有[(ngModel)]
指令且未包含在表单中的标记中。如果我不添加它,我会得到一个错误:
ERROR Error: No value accessor for form control with unspecified name attribute
好的,如果我把这个属性放在那里,错误就会消失。但是,等等!没人知道它是干什么的!Angular的医生一点也没提到。当我知道我不需要值访问器时,为什么我需要它?此属性如何连接到值访问器?该指令的作用是什么?什么是值访问器?如何使用它?
为什么每个人都在做他们根本不理解的事情?只要加上这行代码就行了,谢谢,这不是写好程序的方法。
然后呢。我读了不是一个而是两个关于Angular表单的大型指南和一个关于ngModel
的部分:
你知道吗?没有提到值访问器或ngDefaultControl
。它在哪里?
第三方控件需要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源代码,我很好奇为什么某些函数以两个美元符号开头。这是某种约定吗? 问题答案: 单个,用于保留公共标识符 保留 专用 标识符的双精度 引用文档: $前缀命名约定 … 如果您检查范围,您可能还会注意到一些以$$开头的属性。这些属性被认为是私有的,不应访问或修改。