2017-04-19 51 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(開始,結束);'爲我工作。這是非常酷的人。 –

相關問題