2017-04-19 20 views
6

在名称字段中有一些限制,所以我试图使用下面的指令验证名称字段。内部指令我正在使用正则表达式来检查有效的名称,然后使用valueAccessor.writeValue(newVal)Angular 2光标在文本框末尾跳转时更改数据

将有效的名称替换为文本框这里的问题是当我试图键入文本框中的某个单词时光标跳到最后。

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

回答

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); 

注意,当你正在修改的输入可能是不准确的...

+0

'this.el.nativeElement.s etSelectionRange(开始,结束);'为我工作。这是非常酷的人。 –

相关问题