Javascript 光标在ngModelChange Angular/Typescript上结束时出现问题
我的HTML输入字段和使用ngModelChange的typescript组件有问题。我希望能够在任何需要的地方编辑输入值 例如:Javascript 光标在ngModelChange Angular/Typescript上结束时出现问题,javascript,angular,typescript,ngmodel,Javascript,Angular,Typescript,Ngmodel,我的HTML输入字段和使用ngModelChange的typescript组件有问题。我希望能够在任何需要的地方编辑输入值 例如: 原始输入自动填充为“00:00:00”。我想把它编辑成“01:20:00” 我用键盘将光标(^)定位到需要的位置,使其处于0^0:00:00 我输入1,结果是“01:00:00^” 如果我想添加2,我需要再次移动光标,这对我来说是不可取的 我知道这是一个已知的问题,可以通过使用setSelectionRange重新设置光标来解决,但是这不起作用,因为即使我使用s
- 原始输入自动填充为“00:00:00”。我想把它编辑成“01:20:00”
- 我用键盘将光标(^)定位到需要的位置,使其处于0^0:00:00
- 我输入1,结果是“01:00:00^”
- 如果我想添加2,我需要再次移动光标,这对我来说是不可取的
<input
id="value"
type="text"
[ngModel]="changedValue"
(ngModelChange)="formatAndChange($event)"
/>
基本上,我的问题是,如果我们想全部使用这个结构,那么应该如何使用它:值在用户键入时更改并格式化(我们添加冒号以便格式正确),光标保持在原位(ngModelChange不会更改光标的位置,或者至少我可以让它返回到原来的位置)
谢谢。
谢谢 这不太正确: 即使我使用setSelectionRange(selectionStart,selectionEnd)和光标的正确值,ngModelChange也会将光标放回末尾 只要值通过JavaScript更新,浏览器就会将光标放在输入字段的末尾。与棱角无关 让我们看看在输入字段中键入内容时会发生什么。这是一个非常明确的序列:
ngModelChange
fires李>
formattandchange
运行并更新changedValue
李>
formatAndChange
方法已完成)李>
ngModel
的值李>
ngModel
调度一个微任务(我将在回答的末尾解释),它更新实际的输入元素值ngModel
时,ngModelChange
甚至不会触发
如果您试图在格式和更改中设置SelectionRange
,它永远不会起作用,因为会发生以下情况:
changedValue
更新李>
光标放置在输入字段中的预期位置李>
ngModel
,然后更新输入值,将光标移到输入的末尾
要实现这一点,您需要在更新输入值后调用setSelectionRange
,这样至少可以在完成更改检测后调用微任务。以下是更新后的代码(请注意,由于数字之间有冒号,这并不完全正确,但我相信您可以自己解决):
导入{
检查后,
组成部分,
ElementRef,
视图儿童
}从“@angular/core”开始;
@组成部分({
选择器:“我的应用程序”,
templateUrl:“./app.component.html”,
样式URL:['./app.component.css']
})
导出类AppComponent实现AfterViewChecked{
publicchangedvalue:String='00:00:00';
私有值更新:布尔值;
私人选择开始:号码;
私有选择结束:数字;
私有选择方向:“向前”|“向后”|“无”;
@ViewChild('输入')
私有inputRef:ElementRef;
公共formatAndChange(inputValue:string){
console.log(输入值);
const oldChangedValue=this.changedValue;
this.changedValue=输入值;
如果(inputValue.length>8){
inputValue=inputValue.substr(0,8);
}
设unformat=inputValue.replace(/\D/g');
如果(未格式化长度>0){
inputValue=unformat.match(新的RegExp('.{1,2}',g')).join(':');
}
console.log(输入值);
this.changedValue=新字符串(inputValue);
this.valueUpdated=oldChangedValue!==this.changedValue;
if(this.valueUpdated&&this.inputRef.nativeElement){
常量元素=this.inputRef.nativeElement;
this.selectionStart=element.selectionStart;
this.selectionEnd=element.selectionEnd;
this.selectionDirection=element.selectionDirection;
}
}
//此组件的更改检测完成后,将调用此生命周期挂钩
ngAfterViewChecked(){
//这个方法经常被调用,所以我们需要确保我们只在真正需要的时候执行这个逻辑(即值实际上已经改变)
if(this.valueUpdated&&this.inputRef.nativeElement){
this.valueUpdated=false;
//这就是安排微任务的方式
Promise.resolve()然后(()=>{
//请确保更新此文件以处理冒号
this.inputRef.nativeElement.setSelectionRange(
这是selectionStart,
这个.selectionEnd,
这是选择方向
);
});
}
}
}
微任务
微任务基本上是一些代码,在当前调用堆栈清空后执行。Javascript的任务和微任务是Javascript引擎的核心,它们实际上不是那么容易掌握,但是理解起来非常有用
我不知道为什么Angular开发人员决定更新微任务中的输入值,这肯定有他们的原因。如果你没有太多Angular和/或JS的经验,这可能看起来太多了。Angular是一个复杂的框架,您可能需要阅读一些关于变更检测和组件生命周期的内容,以便更好地理解它。
export class AppComponent {
public changedValue: String = "00:00:00";
public formatAndChange(inputValue: string) {
this.changedValue = inputValue;
if (inputValue.length > 8) {
inputValue = inputValue.substr(0, 8);
}
let unformat = inputValue.replace(/\D/g, "");
if (unformat.length > 0) {
inputValue = unformat.match(new RegExp(".{1,2}", "g")).join(":");
}
this.changedValue = new String(inputValue);
}
}