使用replace与光标定位方法时出现光标跳转异常问题
Angular输入框实时转格鲁吉亚语光标跳转问题修复
问题描述
编写了一段Angular代码,实现输入框内容实时转换为格鲁吉亚语的功能,转换功能正常,但在文本中间输入内容时,光标会自动跳转到文本末尾。
原代码
HTML代码
<mat-form-field *ngIf="operationType != 'joint'" [ngClass]="{'inputBIG uniqueStander':item?.person?.factualAddress?.length > 50, 'inputBIG':!item?.person?.factualAddress?.length > 50}" class="inputBIG" appearance="outline"> <mat-label>მისამართი</mat-label> <input autocomplete="off" autocomplete="off" matInput placeholder="" [(ngModel)]="dataaa" name="address" [maxlength]="maxFactAddress" (keyup)="iReplaceToGEO('firstAddr')" id="firstAddr"> </mat-form-field>
TypeScript代码
dataaa: any; public iReplaceToGEO(position?): void { console.log('position', position); if (position) { this.getCaretPosition(position); } this.dataaa = replacer(this.dataaa); if (position) { this.setCaretPosition(position, this.caretPos, this.caretPos); } function replacer(val): string { val = val .replace(/a/g, 'ა') .replace(/b/g, 'ბ') .replace(/c/g, 'ც') .replace(/d/g, 'დ') .replace(/e/g, 'ე') .replace(/f/g, 'ფ') .replace(/g/g, 'გ') .replace(/h/g, 'ჰ') .replace(/i/g, 'ი') .replace(/j/g, 'ჯ') .replace(/k/g, 'კ') .replace(/l/g, 'ლ') .replace(/m/g, 'მ') .replace(/n/g, 'ნ') .replace(/o/g, 'ო') .replace(/p/g, 'პ') .replace(/q/g, 'ქ') .replace(/r/g, 'რ') .replace(/s/g, 'ს') .replace(/t/g, 'ტ') .replace(/u/g, 'უ') .replace(/v/g, 'ვ') .replace(/w/g, 'წ') .replace(/x/g, 'ხ') .replace(/y/g, 'ყ') .replace(/z/g, 'ზ') .replace(/J/g, 'ჟ') .replace(/T/g, 'თ') .replace(/R/g, 'ღ') .replace(/S/g, 'შ') .replace(/C/g, 'ჩ') .replace(/Z/g, 'ძ') .replace(/W/g, 'ჭ'); return val; } } caretPos: number = 0; public getCaretPosition(ctrl) { let arr: any = document.getElementById(ctrl); console.log('getCaretPosition', arr.selectionStart); if (arr.selectionStart || arr.selectionStart == '0') { this.caretPos = arr.selectionStart; return { start: arr.selectionStart, end: arr.selectionEnd, }; } else { this.caretPos = 0; return { start: 0, end: 0, }; } } public setCaretPosition(ctrl, start, end) { let arr: any = document.getElementById(ctrl); console.log('setCaretPosition', arr.setSelectionRange); console.log('start', start); console.log('end', end); if (arr.setSelectionRange) { arr.focus(); arr.setSelectionRange(start, end); } else if (arr.createTextRange) { var range = arr.createTextRange(); range.collapse(true); range.moveEnd('character', end); range.moveStart('character', start); range.select(); } this.caretPos = this.caretPos + 1; }
问题原因
- 使用
keyup事件触发转换,Angular更新ngModel后会重新绑定输入框值,导致光标被重置到末尾。 setCaretPosition方法中this.caretPos = this.caretPos + 1的代码会错误地偏移光标位置。
修复方案
修改后的HTML代码
<mat-form-field *ngIf="operationType != 'joint'" [ngClass]="{'inputBIG uniqueStander':item?.person?.factualAddress?.length > 50, 'inputBIG':!item?.person?.factualAddress?.length > 50}" class="inputBIG" appearance="outline"> <mat-label>მისამართი</mat-label> <input autocomplete="off" matInput placeholder="" [(ngModel)]="dataaa" name="address" [maxlength]="maxFactAddress" (input)="iReplaceToGEO('firstAddr')" id="firstAddr"> </mat-form-field>
修改后的TypeScript代码
dataaa: any; public iReplaceToGEO(position?: string): void { if (!position) return; const inputElement = document.getElementById(position) as HTMLInputElement; // 记录当前光标位置 const caretPosition = inputElement.selectionStart; // 执行文本转换 this.dataaa = replacer(this.dataaa); // 等待Angular完成DOM更新后恢复光标位置 setTimeout(() => { inputElement.focus(); inputElement.setSelectionRange(caretPosition, caretPosition); }, 0); function replacer(val: string): string { return val .replace(/a/g, 'ა') .replace(/b/g, 'ბ') .replace(/c/g, 'ც') .replace(/d/g, 'დ') .replace(/e/g, 'ე') .replace(/f/g, 'ფ') .replace(/g/g, 'გ') .replace(/h/g, 'ჰ') .replace(/i/g, 'ი') .replace(/j/g, 'ჯ') .replace(/k/g, 'კ') .replace(/l/g, 'ლ') .replace(/m/g, 'მ') .replace(/n/g, 'ნ') .replace(/o/g, 'ო') .replace(/p/g, 'პ') .replace(/q/g, 'ქ') .replace(/r/g, 'რ') .replace(/s/g, 'ს') .replace(/t/g, 'ტ') .replace(/u/g, 'უ') .replace(/v/g, 'ვ') .replace(/w/g, 'წ') .replace(/x/g, 'ხ') .replace(/y/g, 'ყ') .replace(/z/g, 'ზ') .replace(/J/g, 'ჟ') .replace(/T/g, 'თ') .replace(/R/g, 'ღ') .replace(/S/g, 'შ') .replace(/C/g, 'ჩ') .replace(/Z/g, 'ძ') .replace(/W/g, 'ჭ'); } }
修复说明
- 替换事件类型:将
keyup改为input事件,确保输入值变化时立即触发转换,避免按键延迟导致的光标问题。 - 简化光标处理逻辑:直接在转换函数内获取和恢复光标位置,移除冗余的
getCaretPosition和setCaretPosition方法。 - 移除错误代码:删除原代码中导致光标偏移的
this.caretPos = this.caretPos + 1语句。 - 确保DOM更新后恢复光标:使用
setTimeout延迟执行光标恢复操作,等待Angular完成输入框值的绑定更新,保证光标位置设置生效。
内容的提问来源于stack exchange,提问作者nevaehteekay
相关产品推荐
相关产品推荐

