【问题标题】:Angular 2 Cursor jump at the end of textbox when changing dataAngular 2光标在更改数据时跳转到文本框的末尾
【发布时间】:2017-04-19 10:00:43
【问题描述】:

名称字段有一些限制,因此我尝试使用如下指令验证名称字段。内部指令我使用正则表达式检查有效名称,然后使用 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);
    }
}

【问题讨论】:

    标签: angular angular2-directives


    【解决方案1】:

    这源于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);
    

    请注意,在您修改输入时它可能不准确...

    【讨论】:

    • this.el.nativeElement.setSelectionRange(start,end); 为我工作。这是一个很酷的人。
    猜你喜欢
    • 2020-02-21
    • 1970-01-01
    • 1970-01-01
    • 2011-08-17
    • 2015-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多