2016-12-02 76 views
4

我有一个Angular2指令的问题,应该做到以下几点:Angular2 keyup事件更新ngModel光标位置跳到结束

  • 如果用户输入检测“”字符。
  • 如果下一个字符也是'。',请删除重复的'。'。并将光标位置移动到'。'之后。 char

我有上面的工作,但是,当与ngModel结合使用时,光标位置会在每次更新模型时跳转到最后。

输入:

<input type="text" name="test" [(ngModel)]="testInput" testDirective/> 

的指令:

import {Directive, ElementRef, Renderer, HostListener, Output, EventEmitter} from '@angular/core'; 

@Directive({ 
    selector: '[testDirective][ngModel]' 
}) 
export class TestDirective { 


    @Output() ngModelChange: EventEmitter<any> = new EventEmitter(); 

    constructor(private el: ElementRef, 
    private render: Renderer) { } 

    @HostListener('keyup', ['$event']) onInputChange(event) { 
    // get position 
    let pos = this.el.nativeElement.selectionStart; 

    let val = this.el.nativeElement.value; 

    // if key is '.' and next character is '.', skip position 
    if (event.key === '.' && 
     val.charAt(pos) === '.') { 

     // remove duplicate periods 
     val = val.replace(duplicatePeriods, '.'); 

     this.render.setElementProperty(this.el.nativeElement, 'value', val); 
     this.ngModelChange.emit(val); 
     this.el.nativeElement.selectionStart = pos; 
     this.el.nativeElement.selectionEnd = pos; 

    } 
    } 
} 

这工作,除了光标位置跳转到结束。删除线:

this.ngModelChange.emit(val); 

修复问题和光标位置是正确的,但模型不更新。

任何人都可以推荐一个解决方案吗?或者,也许我正在采取错误的方法解决问题?

谢谢

回答

6

您需要在setTimeout()调用中包装以下行。原因是您需要给浏览器时间来呈现新值,并且只有在新值呈现后更改光标位置才会被重置。不幸的是,这会造成一些闪烁,但我无法找到任何其他方式使其工作。

setTimeout(() => { 
    this.el.nativeElement.selectionStart = pos; 
    this.el.nativeElement.selectionEnd = pos; 
}); 
+1

我可以证实这确实起作用,并且闪烁不是很明显。这是可以接受的解决方案。不过,我希望能够在不使用setTimeout的情况下找到解决方案。 – conor

1

对于我的情况下,不使用的setTimeout可以接受的解决办法是:

  1. 不上KEYUP更新模型
  2. 更新模型上,而不是事件的内容

    @HostListener('focusout') focusOut() { 
        this.ngModelChange.emit(this.el.nativeElement.value); 
    }