gpt4 book ai didi

javascript - 自定义表单控件 (ControlValueAccessor) 的绑定(bind) ngModel 总是将表单设置为脏状态

转载 作者:太空狗 更新时间:2023-10-29 18:24:16 24 4
gpt4 key购买 nike

我正在尝试实现一个非常简单的自定义表单控件。

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

但我的问题是,当我以(响应式(Reactive))形式使用它时,只需设置 [(ngModel)] 评估 form.dirtytrue,但如果我使用普通输入控件,一切都会按预期工作。

enter image description here

<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

最佳答案

编辑:经过一些修改后,我终于找到了我认为应该是正确的实现方式。

我简直不敢相信我从来没有在网上找到很好的解释 onChangewriteValue 函数如何对应于脏/原始状态以及如何处理重置。

只要您调用 onChange,您的控件就会被设置为 dirty: true。调用 form.reset() 将重置此状态,但也会调用 writeValue 来设置新值。所以永远不要在此方法中调用onChange,因为它会破坏您的状态。

在我的实现中,我有一个简单的 setter 用于我的值,我在其中调用 onChange 来实际设置正确的状态,因为 setter 仅由我的模板中的输入控件调用。

您的控件可能会对值的实际更改方式进行更复杂的处理,但只要您实际调用 onChange 如果您想将更改反射(reflect)到外部并且您可以设置使用 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; }
}

关于javascript - 自定义表单控件 (ControlValueAccessor) 的绑定(bind) ngModel 总是将表单设置为脏状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48887030/

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