名称字段有一些限制,所以我尝试使用指令验证名称字段,如下所示。 Inside指令我使用正则表达式检查有效名称,然后使用valueAccessor.writeValue(newVal)
这里的问题是当我试图在文本框光标跳转中输入某个单词的中间部分时。
@Directive({
selector: '[validateName]',
host: {
'(ngModelChange)': 'onInputChange($event, false)',
'(keydown.backspace)': 'onInputChange($event.target.value, true)',
'(focusout)': 'removeClass()'
}
})
export class NameValidator {
constructor(public model: NgControl,public renderer: Renderer, public el: ElementRef) { }
onInputChange(event, backspace) {
if (!backspace) {
// Remove invalid characters (keep only valid characters)
var newVal = event.replace(/^[0-9\s]/g, '').replace(/[^A-Za-z0-9_$]/g,'');
// Add class for invalid name.
if (/^[0-9\s]/g.test(event) || /[^A-Za-z0-9_$]/g.test(event)) {
this.renderer.setElementClass(this.el.nativeElement, 'invalid-name', true);
}
else {
this.renderer.setElementClass(this.el.nativeElement, 'invalid-name', false);
}
// set the new value
this.model.valueAccessor.writeValue(newVal);
}
}
removeClass() {
this.renderer.setElementClass(this.el.nativeElement, 'invalid-name', false);
}
}
答案 0 :(得分:3)
这是因为DefaultValueAccessor
盲目地写了元素值,如果有焦点或不焦点,选择与否。我必须自己处理这样的行为,因为我正在使用自动保存的表单,我不得不重写DefaultValueAccessor
并创建一个只有写入值的文件(如果不同的话)(我不认为会对你有用,见下文):
export const DEFAULT_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => DefaultValueAccessor),
multi: true
};
@Directive({
selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]",
host: {"(input)": "onChange($event.target.value)", "(blur)": "onTouched()"},
providers: [DEFAULT_VALUE_ACCESSOR]
})
export class DefaultValueAccessor implements ControlValueAccessor {
onChange = (_: any) => {
};
onTouched = () => {
};
constructor(private _renderer: Renderer, private _elementRef: ElementRef) {
}
writeValue(value: any): void {
const normalizedValue = value == null ? "" : value;
// line bellow is the only line I added to the original one
if ((this._elementRef.nativeElement as HTMLInputElement).value !== normalizedValue)
this._renderer.setElementProperty(this._elementRef.nativeElement, "value", normalizedValue);
}
registerOnChange(fn: (_: any) => void): void {
this.onChange = fn;
}
registerOnTouched(fn: () => void): void {
this.onTouched = fn;
}
setDisabledState(isDisabled: boolean): void {
this._renderer.setElementProperty(this._elementRef.nativeElement, "disabled", isDisabled);
}
}
对于您的情况,您可能需要处理输入选择:
let start=this.el.nativeElement.selectionStart;
let end = this.el.nativeElement.selectionEnd;
this.model.valueAccessor.writeValue(newVal);
this.el.nativeElement.setSelectionRange(start,end);
请注意,在修改输入时可能不准确...