问题描述
长话短说,我目前正在研究一个指令,该指令在修改时将函数应用于控制值。该函数仅在模型侧修改控制值。事情是这样的:
// import ...
// @Directive
export class ControlValuePipeDirective implements OnInit{
@input() ngxControlValuePipe?: (value? :any) => any;
constructor(
private ngControl: NgControl
) {}
ngOnInit(): void {
if (this.ngxControlValuePipe === undefined) {
console.info("No method was provided to the ngxControlValuePipe directive. Ignoring it.")
}else{
this.ngControl.valueAccessor?.registerOnChange((value: any) => {
this.ngControl.control?.patchValue(this.ngxControlValuePipe ?
this.ngxControlValuePipe(value) : value,{emitModelToViewChange: false})
}
)
}
}
}
我遇到的问题是当我像这样将验证器添加到控件时:
// import ...
// @Component
export class AppComponent {
public profileForm: FormGroup;
constructor() {
const streetControl = new FormControl('',[Validators.maxLength(10)]);
// this.profileForm = ...
}
public editValueOnTheFly(value: any): any{
return value + ' this more than ten chars length string';
};
}
<!-- more html -->
<input id="street" type="text" formControlName="street" [ngxControlValuePipe]="editValueOnTheFly">
<!-- more html -->
如果我的 streetControl 控件值在视图中被修改,那么模型将使用 editValueOnTheFly
方法进行编辑,该方法将一个长字符串添加到模型值中。这将触发验证并使控件无效,因为新模型值超过 10 个字符。
解决方法
因为您想避免对 ControlValuePipeDirective 修改的值进行验证,我建议您将数据模型和表单模型分开。
ControlValuePipeDirective 不应更新表单的模型:
export class ControlValuePipeDirective implements OnInit{
...
ngOnInit(): void {
if (!this.ngxControlValuePipe) { return; }
this.ngControl.valueAccessor?.registerOnChange((value: any) => {
this.ngxControlValuePipe(value);
}
}
}
AppComponent 的 editValueOnTheFly 将负责配置文件模型更新:
interface ProfileModel {
street: string;
...
}
export class AppComponent {
public profileForm: FormGroup;
private profileModel: ProfileModel;
...
public editValueOnTheFly(value: any): any{
const updatedValue = value + ' this more than ten chars length string';
this.profileModel = { ...this.profileModel,street: updatedValue };
}
}
还可以将 profileModel 字段替换为 Subject,以便能够订阅配置文件模型的更改。