I am looking to setup emojis to my chat-app project. I really liked the emojis in slack / tweeter and I would like to have something similar.
I found the following libraries: (if anyone can suggest a better library I would love to hear)
I am not sure how to load these libraries and use them in a VueJS app. Could anyone please assist with how to load and use them?
I would like to mention I tried to use emoji-mart-vue but not sure how to add the the component to the template at run time.
Thanks a lot
tldr; Checkout demo and code on JSFiddle
This answer is divided into two parts. First part deals with how to import
all the stuff into the environment while the second part deals with how to use it Vue.
This solution uses EmojiOne as the emoji provider and EmojioneArea to provide emoji autocomplete behavior.
There are three ways in which you can do this.
Using Global <script>
tag (not recommended for anything serious): You can add the <script>
tags for all the dependencies in order and simply start using the Global objects.
Add these <script>
in order:
https://code.jquery.com/jquery-3.3.1.min.js
https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.min.js
https://cdn.jsdelivr.net/npm/emojione@3.1.6/lib/js/emojione.min.js
https://cdnjs.cloudflare.com/ajax/libs/jquery.textcomplete/1.8.4/jquery.textcomplete.min.js
https://cdnjs.cloudflare.com/ajax/libs/emojionearea/3.4.1/emojionearea.min.js
Using AMD modules (using require.js
): You can use the following configuration to load these modules asynchronously using require.js
require.config({
paths: {
'jquery': 'https://code.jquery.com/jquery-3.3.1',
'Vue': 'https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue',
'emojione': 'https://cdn.jsdelivr.net/npm/emojione@3.1.6/lib/js/emojione',
'jquery.textcomplete': 'https://cdnjs.cloudflare.com/ajax/libs/jquery.textcomplete/1.8.4/jquery.textcomplete',
'emojionearea': 'https://cdnjs.cloudflare.com/ajax/libs/emojionearea/3.4.1/emojionearea'
},
shim: {
'emojione': {
'exports': 'emojione'
}
}
})
You can then require these modules in your entry point as
require(['jquery', 'Vue', 'emojione'], function($, Vue, emojione){ /* ... */ })
Using webpack
: All the above libraries are available via npm
and you install and use them just as you would do with any other library. No special config required.
BONUS: Using webpack
with require.js
and offloading network and caching loads to CDN!
I often use this setup for my projects and this improves reliability and performance of your site. You can use webpack.externals
to instruct webpack
to not bundle any vendor dependencies and instead you provide them yourself, either by manually adding <script>
tags or using require.js
.
Start by adding this to your webpack.<whatever>.js
//...
output: {
libraryTarget: 'umd' // export app as a library
},
//...
externals: {
'jquery': 'jquery',
'vue': 'Vue',
'emojione': 'emojione'
},
//...
Then, in your require.js
entry, add this
//...
map: {
// any module requesting jquery should get shield
"*": {
"jquery": "jquery-shield"
},
// shield should get original jquery
"jquery-shield": {
"jquery": "jquery"
},
// patch plugins
"jquery.textcomplete": {
"jquery": "jquery"
},
"emojionearea": {
"jquery": "jquery"
}
}
//...
// define shield, require all the plugins here
define('jquery-shield', ['jquery', 'jquery-textcomplete', 'emojionearea'], function($){ return $ })
and then add require(...)
your webpack bundle
As the OP mentioned his/her case is to use emojis in a chat app, I would also explain the solution with that case, though this can (and should) be modified for other use cases too!
The solution focuses on two aspects. First is to simply display the emoji in a message
component, i.e., no need to display an emoji picker dialog and second is to display a emoji picker dialog whilst the user is typing into (say) a textarea.
To achieve the first goal, you can use a message component like,
Vue.component('message', {
props: ['content'],
render: function(h){
return h('div', {
class: { 'message': true }
}, [
h('div', {
class: { 'bubble': true },
domProps: {
innerHTML: emojione.toImage(this.content)
}
})
])
}
})
This would create a <message />
component which you can use as
<message content="Hey :hugging:!!" />
which will render
<div class="message">
<div class="bubble">
Hey <img class="emojione" alt="🤗" title=":hugging:" src="...">!!
</div>
</div>
Now, to create a <message-box />
component that will display an emoji picker to assist in autocomplete
, do as follows
Vue.component('message-box', {
template: `<div class="message-box"><textarea></textarea></div>`,
mounted(){
// find the input
$(this.$el).find('textarea').emojioneArea()
}
})
And that's it! Although it may seem like a lot, the crux of the solution is quiet simple! Just use emojione.toImage(str)
to get a DOM string
and apply it to the Vue component (you can also use v-html
to do this but IMO render()
is a bit more sleek!). And for the displaying the picker, you just call $(...).emojioneArea()
on the <textarea />
once the component is mounted.
Make sure to checkout full code example at https://jsfiddle.net/riyaz_ali/5Lhex13n