[ngDefaultControl]
Üçüncü şahıs kontrolleri ControlValueAccessor, açısal formlarla işlev görmesini gerektirir . Polimer gibi birçoğu yerel öğe <paper-input>gibi davranır <input>ve bu nedenle DefaultValueAccessor. Bir ngDefaultControlöznitelik eklemek, bu yönergeyi kullanmalarına izin verecektir.
<paper-input ngDefaultControl [(ngModel)]="value>
veya
<paper-input ngDefaultControl formControlName="name">
Dolayısıyla, bu zarafetin tanıtılmasının ana nedeni budur.
Angular2'nin alfa sürümlerindeng-default-control öznitelik olarak adlandırıldı .
Yani ngDefaultControliçin seçicileri biridir DefaultValueAccessor yönergesi:
@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 {
Bunun anlamı ne?
Bu, kendi değer erişimcisine sahip olmayan öğeye (polimer bileşeni gibi) bu niteliği uygulayabileceğimiz anlamına gelir. Yani bu öğe davranışını alacak DefaultValueAccessorve bu öğeyi açısal formlarla kullanabiliriz.
Aksi takdirde, kendi uygulamanızı sağlamanız gerekir. ControlValueAccessor
ControlValueAccessor
Açısal belge durumları
Bir ControlValueAccessor, Angular form API'si ile DOM'daki yerel bir öğe arasında bir köprü görevi görür.
Aşağıdaki şablonu basit angular2 uygulamasında yazalım:
<input type="text" [(ngModel)]="userName">
inputYukarıdakilerin nasıl davranacağını anlamak için bu öğeye hangi direktiflerin uygulandığını bilmemiz gerekir. Burada açısal, hatayla ilgili bazı ipuçları verir:
İşlenmemiş Promise reddi: Şablon ayrıştırma hataları: Bilinen bir 'input' özelliği olmadığı için 'ngModel'e bağlanamaz.
Tamam, bu kadar açık ve cevap alabilirsiniz: ithalat FormsModuleadresinden Müşteri @NgModule:
@NgModule({
imports: [
...,
FormsModule
]
})
export AppModule {}
Biz onu ve tüm işleri amaçlandığı gibi ithal ettik. Ama kaputun altında neler oluyor?
FormsModule , bizim için aşağıdaki yönergeleri dışa aktarır:
@NgModule({
...
exports: [InternalFormsSharedModule, TEMPLATE_DRIVEN_DIRECTIVES]
})
export class FormsModule {}

Biraz araştırdıktan sonra, üç direktifin bizim için uygulanacağını keşfedebiliriz. input
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,
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 {
NgControlStatusyönerge sadece zaman değiştirdiği sınıfları gibi ng-valid, ng-touched, ng-dirtyve biz burada atlayabilirsiniz.
DefaultValueAccesstorNG_VALUE_ACCESSORsağlayıcılar dizisinde belirteç sağlar :
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 {
NgModelyönerge NG_VALUE_ACCESSOR, aynı konak öğesinde bildirilen yapıcı belirtecine enjekte eder .
export NgModel extends NgControl implements OnChanges, OnDestroy {
constructor(...
@Optional() @Self() @Inject(NG_VALUE_ACCESSOR) valueAccessors: ControlValueAccessor[]) {
Bizim durumumuzda NgModelenjekte edecek DefaultValueAccessor. Ve şimdi NgModel yönergesi paylaşılan setUpControlişlevi çağırıyor :
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) => {
dir.valueAccessor !.writeValue(newValue);
if (emitModelEvent) dir.viewToModelUpdate(newValue);
});
}
Ve işte köprü iş başında:

NgModelkontrolü (1) kurar ve dir.valueAccessor !.registerOnChangeyöntemi çağırır . ControlValueAccessorgeri aramayı onChange(2) özelliğinde depolar ve inputolay gerçekleştiğinde bu geri aramayı başlatır (3) . Ve son olarak updateControlişlev, geri arama içinde çağrılır (4)
function updateControl(control: FormControl, dir: NgControl): void {
dir.viewToModelUpdate(control._pendingValue);
if (control._pendingDirty) control.markAsDirty();
control.setValue(control._pendingValue, {emitModelToViewChange: false});
}
açısal çağrıların API'yi oluşturduğu yer control.setValue.
Bu, nasıl çalıştığının kısa bir versiyonu.