Skip to content

Instantly share code, notes, and snippets.

@lentschi
Last active May 1, 2020 10:35
Show Gist options
  • Save lentschi/8600f9b6ea7e7f5178f40a36f3053de7 to your computer and use it in GitHub Desktop.
Save lentschi/8600f9b6ea7e7f5178f40a36f3053de7 to your computer and use it in GitHub Desktop.
Angular 2+ pipe to replace emoji-mart emojis with an html element displaying their image representation
@Arjun-Shinojiya
Copy link

Is it possible to use this pipe from the ts file?

@Arjun-Shinojiya You mean from the component? Yes, that is possible - just add the Pipe to your module's providers array and then inject it - as you would inject any service.

I still don't know, what it is exactly, that you're trying to accomplish - It sounds like you're building some kind of chat where you can view messages containing unicode emojis (using the pipe), edit them (using a contenteditable with the preparsed html content containing spans instead of unicode emojis), and then save them back to the server (transforming the spans back to unicode emojis) - Is that it?

If so, here's a small sample for that:
https://stackblitz.com/edit/replaceemojis-editor?file=src%2Fapp%2Fapp.component.html

Just to be clear about this: If you don't mind saving spans with hardcoded emoji background image styles on your server, then you don't need my pipe at all. (The downside of saving them with hardcoded styles is, that it will be hard to change styles/image paths etc. afterward - That would require a html migration on the server-side.)

@lentchi Thank you for your reply. I will try this solution. Let me explain to you what problem I am currently facing. I have one feed page ,please check below image.
Screenshot from 2019-12-24 10-54-29
So In feed I added our emoji span with text coming from API also with that I have one shorten pipe for Read more and Read less in the feed. Our pipe works with inner HTML in div of p tag. And ngx shorten pipe works between p tag. These both pipe is not working together currently. If It works together still shorten pipe calculates span tags also with characters and that's why read more and read less will come incorrect. Below is my HTML code.
<p class="feeddescription" [innerHTML]="feed.description | replaceEmojis:sheet:size:sheetSize:backgroundImageFn : feed.description"> {{feed.description | shorten: feed.maxLength: '...'}} <a href="javascript:void(0);" *ngIf="feed.description.length > feed.maxLength" (click)="feed.maxLength = feed.description.length">Read more</a> <a href="javascript:void(0);" *ngIf="feed.description.length == feed.maxLength" (click)="feed.maxLength = maxLength">Read less</a> </p>
I wrote like this both pipes but shorten pipe is not working. Thats why I am finding solution to save emoji and text only in database instead of span tag

@lentschi
Copy link
Author

lentschi commented Dec 24, 2019

@Arjun-Shinojiya Like this?: https://stackblitz.com/edit/replaceemojis-runes-truncate?file=src%2Fapp%2Fapp.component.html

If that's what you need, some explanations:

  1. A simple text.substr won't do when trying to truncate emojis UTF-8 characters. In this sample I used runes - see https://stackoverflow.com/questions/52526719/javascript-substring-without-splitting-emoji
  2. This sample doesn't allow for any HTML content in the text you're trying to truncate (It will be escaped as truncating HTML isn't so easy).
    Note: If you do have HTML content, I suggest converting it to text before. (Having any formatting combined with an ellipsis could be considered a design flaw anyway.)

@Arjun-Shinojiya
Copy link

Is it possible to use this pipe from the ts file?

@Arjun-Shinojiya You mean from the component? Yes, that is possible - just add the Pipe to your module's providers array and then inject it - as you would inject any service.

I still don't know, what it is exactly, that you're trying to accomplish - It sounds like you're building some kind of chat where you can view messages containing unicode emojis (using the pipe), edit them (using a contenteditable with the preparsed html content containing spans instead of unicode emojis), and then save them back to the server (transforming the spans back to unicode emojis) - Is that it?

If so, here's a small sample for that:
https://stackblitz.com/edit/replaceemojis-editor?file=src%2Fapp%2Fapp.component.html

Just to be clear about this: If you don't mind saving spans with hardcoded emoji background image styles on your server, then you don't need my pipe at all. (The downside of saving them with hardcoded styles is, that it will be hard to change styles/image paths etc. afterwards - That would require a html migration on the server side.)

@lentschi I think your this example will work for me but it has one issue.
After adding emoji in div ,it wont displaying text after it . I am able to add the text after emoji but it wont get show.

@lentschi
Copy link
Author

@Arjun-Shinojiya Sorry, I'm not sure what you mean to say. In my sample there is text after the last emoji and it is displayed. Could you maybe create a failing StackBlitz sample? (Then I might be able to help.)

@Arjun-Shinojiya
Copy link

@lentschi In your this example https://stackblitz.com/edit/replaceemojis-editor?file=src%2Fapp%2Fapp.component.html . I changed the line number 40 code to
this.editorHtml = this.sanitizer.bypassSecurityTrustHtml(span.outerHTML + this.contenteditable.nativeElement.innerHTML); .I done this because I want to insert emoji after last character of the sentence . Its working fine but now the issue is when I insert the emoji and after that if I type any word or character then It won't get display but after clicking on save button, the entered text gets displayed. Hope you understand the issue.

@lentschi
Copy link
Author

lentschi commented Jan 24, 2020

@Arjun-Shinojiya Ah, that was because you also need to set span.setAttribute('contenteditable', 'false'); for the newly inserted emoji. (Else you type text into the emoji span, which cannot be seen)
I updated the StackBlitz sample and also added a way of inserting the emoji at the current cursor position (if the editor is focused otherwise it will appear at the end).

This is still far from being a perfect editor (It's just a sample on how to use the pipe!). For example the focus on the contenteditable will be lost after inserting an emoji. I think to prevent that you will have to remove the input [innerHTML]="editorHtml" and handle setting the html in the component code. (Otherwise the content will be replaced and the cursor position is lost)
Also note, there's some issue with deleting emojis in current Firefox versions with the backspace key (interestingly the delete key works). I googled a bit and there seems to be a workaround, but I haven't implemented it (out of the scope of this sample too.)

@asdrubalivan
Copy link

asdrubalivan commented Apr 2, 2020

Hello, I'm getting the following

Argument of type '(set: string, sheetSize: number) => string' is not assignable to parameter of type 'number'

Any help? I'm using version 3.0.3 of emoji mart. They added a new param called sheetRows which is a number in here

                    const styles = this.emojiService.emojiSpriteStyles(
                        matchingData.sheet,
                        set,
                        size,
                        sheetSize,
                        backgroundImageFn
                    );

Just between sheetSize and backgroundImageFn

@lentschi
Copy link
Author

lentschi commented Apr 5, 2020

@asdrubalivan I haven't had time to try this out yet, but the new sheetRows parameter is optional - could you not just replace it with undefined and it would still work?

@lentschi
Copy link
Author

lentschi commented Apr 13, 2020

@asdrubalivan I fixed it, but not in the Gist: Due to the ongoing popularity of this Gist, I decided to turn it into a library after all:
npmjs.com: https://www.npmjs.com/package/ng-utf8-emojis-to-images
GitHub: https://github.com/lentschi/ng-utf8-emojis-to-images

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment