I have a text-area and I am using NGX Emoji mart to insert emojis into that text-area. Before inserting any emoji's I am getting the current caret position of the text-area then pushing the emoji into the ngModel.
Issue If I write something in the text-area then if I choose an emoji, for the first time it is inserting in the correct position(correct position), after that the emojis are inserting at the beginning.
Question How I can insert the selected emoji in correct caret position?
For emoji I am using this plugin - https://www.npmjs.com/package/@ctrl/ngx-emoji-mart
For Caret Position I am using Tim Down's approach - Get caret position in HTML input?
Component.html
<div class="message-block">
<textarea class="message-textarea" #messageElement [(ngModel)]="message" (ngModelChange)="onChangeMessage()"
placeholder="enter your message here.."></textarea>
<div class="emoji-picker-btn" (click)="isEmojiDropdownShown = !isEmojiDropdownShown"></div>
</div>
<div class="emoji-picker" *ngIf="isEmojiDropdownShown">
<emoji-mart (emojiSelect)="onSelectEmoji($event)" isNative="true" perLine="7" showPreview="false">
</emoji-mart>
</div>
Component.ts
public message : string = '';
@ViewChild('messageElement', { static: false }) messageElement: ElementRef;
onChangeMessage(){
console.log('model on change');
}
onSelectEmoji(event : any){
let messageEl : HTMLElement = this.messageElement.nativeElement;
let caretPosition = this.getCaretPosition(withoutPatternEl).start;
this.message = [this.message.slice(0, caretPosition), event.emoji.native,
this.message.slice(caretPosition)].join('');
}
Caret position
getCaretPosition(el : any){
let start : number = 0;
let end : number = 0;
let normalizedValue : any;
let range : any;
let textInputRange : any;
let len : any;
let endRange : any;
if (typeof el.selectionStart == "number" && typeof el.selectionEnd == "number") {
start = el.selectionStart;
end = el.selectionEnd;
} else {
range = (<any>document).selection.createRange();
if (range && range.parentElement() == el) {
len = el.value.length;
normalizedValue = el.value.replace(/\r\n/g, "\n");
// Create a working TextRange that lives only in the input
textInputRange = el.createTextRange();
textInputRange.moveToBookmark(range.getBookmark());
// Check if the start and end of the selection are at the very end
// of the input, since moveStart/moveEnd doesn't return what we want
// in those cases
endRange = el.createTextRange();
endRange.collapse(false);
if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) {
start = end = len;
} else {
start = -textInputRange.moveStart("character", -len);
start += normalizedValue.slice(0, start).split("\n").length - 1;
if (textInputRange.compareEndPoints("EndToEnd", endRange) > -1) {
end = len;
} else {
end = -textInputRange.moveEnd("character", -len);
end += normalizedValue.slice(0, end).split("\n").length - 1;
}
}
}
}
return {
start: start,
end: end
};
}