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);
Исправлена ошибка, и положение курсора правильное, однако модель не обновляется.
Может ли кто-нибудь порекомендовать решение этой проблемы? Или, может быть, я неправильно подхожу к проблеме?
Спасибо
3 ответов:
Вам нужно обернуть следующие строки в вызове setTimeout (). Причина в том, что вам нужно дать браузеру время для отображения нового значения и только затем изменить положение курсора, которое сбрасывается после отображения нового значения. К сожалению, это вызовет небольшое мерцание, но я не смог найти никакого другого способа заставить его работать.
setTimeout(() => { this.el.nativeElement.selectionStart = pos; this.el.nativeElement.selectionEnd = pos; });
В моем случае приемлемым решением без использования setTimeout было:
- Не обновлять модель на keyup
Обновите модель вместо этого на focusout
@HostListener('focusout') focusOut() { this.ngModelChange.emit(this.el.nativeElement.value); }
Вы можете изменить положение курсора без setTimout() и мерцания, как предложено в принятом ответе с помощью setSelectionRange () следующим образом:
this.el.nativeElement.setSelectionRange(position, position, 'none');
Comments