gpt4 book ai didi

javascript - Angular 中的 ngDefaultControl 是什么?

转载 作者:IT王子 更新时间:2023-10-29 02:50:33 28 4
gpt4 key购买 nike

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

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

好的,如果我把这个属性放在那里,错误就会消失。可是等等!没有人知道它的作用! Angular 的文档根本没有提到它。当我知道我不需要值访问器时,为什么还需要它?这个属性如何连接到值访问器?这个指令有什么作用?什么是值访问器以及如何使用它?

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

然后。我读了两本有关 Angular 表单的大量指南有关 ngModel 的部分:

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

最佳答案

[ngDefaultControl]

第三方控件需要 ControlValueAccessor以 Angular 形式发挥作用。其中很多,例如 Polymer 的 <paper-input> , 表现得像 <input>原生元素,因此可以使用 DefaultValueAccessor .添加 ngDefaultControl属性将允许他们使用该指令。

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

<paper-input ngDefaultControl formControlName="name">

所以这就是引入这个属性的主要原因。

它被称为 ng-default-control属性 in alpha versions of angular2 .

所以 ngDefaultControlDefaultValueAccessor 的选择器之一指令:

@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 采取行为我们可以将此元素与 Angular 形式一起使用。

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

控制值访问器

Angular docs states

A ControlValueAccessor acts as a bridge between the Angular forms API and a native element in the DOM.

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

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

了解我们的 input上面的行为我们需要知道哪些指令应用于此元素。这里 angular 给出了一些错误提示:

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

好的,我们可以打开SO并得到答案:import FormsModule给你的@NgModule :

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

我们导入它并且所有工作都按预期进行。但幕后发生了什么?

FormsModule为我们导出以下指令:

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

enter image description here

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

1) NgControlStatus

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

2) NG模型

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

3) 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 {

NgControlStatus指令只是操纵类似 ng-valid 的类, ng-touched , ng-dirty我们可以在这里省略它。


DefaultValueAccesstor提供 NG_VALUE_ACCESSOR提供者数组中的 token :

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指令在构造函数中注入(inject) NG_VALUE_ACCESSOR在同一宿主元素上声明的标记。

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

在我们的案例中 NgModel将注入(inject) DefaultValueAccessor .现在 NgModel 指令调用共享 setUpControl功能:

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);
});
}

下面是正在运行的桥梁:

enter image description here

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

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

angular 调用形式 API control.setValue .

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

关于javascript - Angular 中的 ngDefaultControl 是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46465891/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com