[英]ControlValueAccessor on Custom Form Component in Dynamic Form
[英]Binding ngModel of custom form control (ControlValueAccessor) always sets form to dirty state
我正在嘗試實現一個非常簡單的自定義表單控件。
@Component({
selector: 'text-input',
template: '<input [(ngModel)]="value" />',
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => TextInputComponent),
multi: true
}]
})
export class TextInputComponent implements ControlValueAccessor {
private _value: any;
get value(): any { return this._value; }
set value(value: any) { return this.writeValue(value); }
writeValue(value: any) {
if (value !== this._value) {
this._value = value;
this.onChange(value);
}
}
onChange = (x: any) => { };
onTouched = () => { };
registerOnChange(fn: (_: any) => void): void { this.onChange = fn; }
registerOnTouched(fn: () => void): void { this.onTouched = fn; }
}
但我的問題是,當我在(反應)形式中使用它時,只需設置[(ngModel)]
form.dirty
計算為true
,但如果我使用普通輸入控件,則一切都按預期工作。
<h2>Hello {{text}}</h2>
<form #f="ngForm" >
<text-input [(ngModel)]="text" name="text"></text-input>
</form>
Dirty: {{f.dirty}}
<form #f2="ngForm" >
<input [(ngModel)]="text" name="text" />
</form>
Dirty: {{f2.dirty}}
我的實施有問題嗎? 如何讓我的自定義控件以dirty
的方式在交互發生時設置為true的方式工作?
Plunkr再現: https ://plnkr.co/edit/FBGAR4uqwen7nfIvHRaC ? p = preview
編輯:經過一些修補我終於找到了我認為應該是正確的實現。
我無法相信我從來沒有在網上找到一個很好的解釋onChange
和writeValue
函數如何對應臟/ prestine狀態以及如何處理重置。
一旦調用onChange
您的控件將被設置為dirty: true
。 調用form.reset()
將重置此狀態,但也調用writeValue
來設置新值。 所以永遠不要在這種方法中調用onChange
,因為它會打破你的狀態。
在我的實現中,我為我的值設置了一個簡單的setter,我在其中調用onChange
來實際設置正確的狀態,因為setter僅由我的模板中的輸入控件調用。
您的控件可能會更復雜地處理值實際更改的方式,但只要您實際調用onChange
如果您想將更改反映到外部,您可以使用writeValue
設置控件的值而不更改狀態一切都會好起來的。
@Component({
selector: 'text-input',
template: `<input [(ngModel)]="value"
(blur)="onTouched()" />`,
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => TextInputComponent),
multi: true
}]
})
export class TextInputComponent implements ControlValueAccessor {
private _value: any;
// NOTE: you could also just bind to a normal field without
// getters and setters and call onChange from your template
// e.g. from (ngModelChange) of the input control
get value(): any { return this._value; }
set value(value: any) {
this.writeValue(value);
this.onChange(value);
}
writeValue(value: any) {
if (value !== this._value) {
this._value = value;
}
}
onChange(x: any) { console.log(x); }
onTouch() { };
registerOnChange(fn: (_: any) => void): void { this.onChange = fn; }
registerOnTouched(fn: () => void): void { this.onTouched = fn; }
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.