3

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
    };
}
Swagata Adhikary
  • 245
  • 5
  • 16

0 Answers0