Angular2 keyup событие update ngModel позиция курсора переходит к концу



У меня возникла проблема с директивой Angular2, которая должна делать следующее:




  • определить, входит ли пользователь '.' характер.

  • Если следующий символ также '.', удалить дубликат '.'и переместите курсор в положение после '.'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);


Исправлена ошибка, и положение курсора правильное, однако модель не обновляется.



Может ли кто-нибудь порекомендовать решение этой проблемы? Или, может быть, я неправильно подхожу к проблеме?

Спасибо

609   3  

3 ответов:

Вам нужно обернуть следующие строки в вызове setTimeout (). Причина в том, что вам нужно дать браузеру время для отображения нового значения и только затем изменить положение курсора, которое сбрасывается после отображения нового значения. К сожалению, это вызовет небольшое мерцание, но я не смог найти никакого другого способа заставить его работать.

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

В моем случае приемлемым решением без использования setTimeout было:

  1. Не обновлять модель на keyup
  2. Обновите модель вместо этого на focusout

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

Вы можете изменить положение курсора без setTimout() и мерцания, как предложено в принятом ответе с помощью setSelectionRange () следующим образом:

this.el.nativeElement.setSelectionRange(position, position, 'none');

Comments

    Ничего не найдено.