angular - 从 ControlValueAccessor 更改 FormControl 值
问题描述
我正在尝试仅为案例创建一个指令。我创建了以下代码,但尝试制作 formGroup.value 时遇到问题。该指令在视觉上改变了值(通过使用_Renderer2),但formControl仍然具有原始值,并且当使用formGroup.value从表单中获取数据时,值是小写的。有可能解决这个问题吗?谢谢
<form [formGroup]="formGroup">
<mat-form-field>
<input placeholder="Street" formControlName="streetName" matInput uppercase>
</mat-form-field>
</form>
import { Directive, ElementRef, Optional, Renderer2, Self } from '@angular/core';
import { ControlValueAccessor, NgControl } from '@angular/forms';
@Directive({
selector: "textarea[uppercase], input[uppercase]",
host: {
'(input)': 'writeValue($event.target.value)',
'(blur)': 'onTouched()',
}
})
export class UppercaseDirective implements ControlValueAccessor {
onChange = (_: any) => {
console.log("onChange", _)
};
onTouched = () => {
console.log("onTouched")
};
constructor(private _renderer: Renderer2, private _elementRef: ElementRef, @Optional() @Self() public ngControl: NgControl) {
ngControl.valueAccessor = this;
}
writeValue(value: any): void {
this._renderer.setProperty(this._elementRef.nativeElement, 'value', this.transformValue(value));
}
registerOnChange(fn: (_: any) => {}): void {
this.onChange = fn;
}
registerOnTouched(fn: () => {}): void {
this.onTouched = fn;
}
setDisabledState(isDisabled: boolean): void {
this._renderer.setProperty(this._elementRef.nativeElement, 'disabled', isDisabled);
}
private transformValue(value: string): string {
return typeof value === 'string'
? value?.toUpperCase()
: value;
}
}
解决方案
您正在混合自定义表单控件和指令的概念。我不知道是否有另一种方法,但是,如果你想制作一个转换一个输入的指令,你可以让它创建一个 HTMLEvent。有些喜欢
@Directive({
selector: "[toUpperCase]"
})
export class ToUpperCaseDirective implements AfterViewInit {
constructor(private elementRef: ElementRef) {}
@HostListener("input", ["$event"]) onKeyDown(event: KeyboardEvent) {
this.setUpper();
}
ngAfterViewInit() {
setTimeout(() => {
this.setUpper();
});
}
setUpper() {
const target = this.elementRef.nativeElement;
let pos = target.selectionStart; //get the position of the cursor
target.value = target.value.toUpperCase();
var evt = document.createEvent("HTMLEvents");
evt.initEvent("input", false, true);
this.elementRef.nativeElement.dispatchEvent(evt);
target.selectionStart = target.selectionEnd = pos; //return the position
}
}
注意:真的,我不认为该指令是解决大写输入问题的好方法。对我来说最好简单地使用 css
<input style="text-transform:uppercase">
然后,当我们要检查值转换时,使用 toUpperCase。
推荐阅读
- dataframe - AWS Glue 动态帧将 csv 写入 s3 且为空
- javascript - 在构造函数中分配的 Sinon 存根类实例
- google-cloud-platform - GCP 上的命名实体识别 (NER)
- python - 仅在 Python asyncio 中处理所有 websocket 消息后返回
- php - 大家好,我在建立连接时遇到错误,谁能帮我解决这个问题......提前谢谢
- apache-spark - Spark 2.3 时间戳减去毫秒
- node.js - 在提交时使用相同的发件人和收件人地址从联系表单发送电子邮件
- amazon-web-services - Amazon Connect 未记录对 S3 存储桶的调用
- python - 使用 Numpy 将一个数组中的值替换为另一个数组中的对应值
- powershell - 在 powershell 中使用嵌套的 foreach