[ngDefaultControl]
Kontrol pihak ketiga membutuhkan a ControlValueAccessorberfungsi dengan bentuk sudut. Banyak dari mereka, seperti Polymer <paper-input>, berperilaku seperti <input>elemen asli dan dengan demikian dapat menggunakan DefaultValueAccessor. Menambahkan ngDefaultControlatribut akan memungkinkan mereka menggunakan arahan itu.
<paper-input ngDefaultControl [(ngModel)]="value>
atau
<paper-input ngDefaultControl formControlName="name">
Jadi inilah alasan utama mengapa atribut ini diperkenalkan.
Itu disebut ng-default-controlatribut dalam versi alfa angular2 .
Jadi ngDefaultControladalah salah satu pemilih untuk direktif DefaultValueAccessor :
@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 {
Apa artinya?
Artinya kita dapat menerapkan atribut ini ke elemen (seperti komponen polimer) yang tidak memiliki pengakses nilainya sendiri. Jadi elemen ini akan mengambil perilaku DefaultValueAccessordan kita dapat menggunakan elemen ini dengan bentuk sudut.
Jika tidak, Anda harus menyediakan implementasi Anda sendiri ControlValueAccessor
ControlValueAccessor
Status dokumen sudut
ControlValueAccessor bertindak sebagai jembatan antara Angular forms API dan elemen asli di DOM.
Mari tulis template berikut dalam aplikasi angular2 sederhana:
<input type="text" [(ngModel)]="userName">
Untuk memahami bagaimana inputperilaku kita di atas, kita perlu mengetahui arahan mana yang diterapkan pada elemen ini. Di sini angular memberikan beberapa petunjuk dengan kesalahan:
Penolakan Janji Tak Tertangani: Kesalahan penguraian template: Tidak dapat mengikat ke 'ngModel' karena bukan properti 'input' yang diketahui.
Oke, kita bisa buka SO dan dapatkan jawabannya: import FormsModuleto your @NgModule:
@NgModule({
imports: [
...,
FormsModule
]
})
export AppModule {}
Kami mengimpornya dan semua bekerja sebagaimana mestinya. Tapi apa yang terjadi di balik terpal?
FormsModule mengekspor untuk kita arahan berikut:
@NgModule({
...
exports: [InternalFormsSharedModule, TEMPLATE_DRIVEN_DIRECTIVES]
})
export class FormsModule {}

Setelah beberapa penyelidikan kita dapat menemukan bahwa tiga arahan akan diterapkan pada kita 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 {
NgControlStatusdirektif hanya memanipulasi kelas seperti ng-valid, ng-touched, ng-dirtydan kita dapat menghilangkan sini.
DefaultValueAccesstormenyediakan NG_VALUE_ACCESSORtoken dalam array penyedia:
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 {
NgModeldirektif memasukkan NG_VALUE_ACCESSORtoken konstruktor yang dideklarasikan pada elemen host yang sama.
export NgModel extends NgControl implements OnChanges, OnDestroy {
constructor(...
@Optional() @Self() @Inject(NG_VALUE_ACCESSOR) valueAccessors: ControlValueAccessor[]) {
Dalam kasus kami NgModelakan menyuntikkan DefaultValueAccessor. Dan sekarang direktif NgModel memanggil setUpControlfungsi bersama :
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);
});
}
Dan inilah jembatan yang sedang beraksi:

NgModelmengatur kontrol (1) dan dir.valueAccessor !.registerOnChangemetode panggilan . ControlValueAccessormenyimpan callback dalam properti onChange(2) dan mengaktifkan callback ini ketika inputperistiwa terjadi (3) . Dan akhirnya updateControlfungsi dipanggil di dalam callback (4)
function updateControl(control: FormControl, dir: NgControl): void {
dir.viewToModelUpdate(control._pendingValue);
if (control._pendingDirty) control.markAsDirty();
control.setValue(control._pendingValue, {emitModelToViewChange: false});
}
di mana panggilan sudut membentuk API control.setValue.
Itu adalah versi singkat dari cara kerjanya.