vue-quick-chat
vue-quick-chat copied to clipboard
Feature: Send Image/Attachments... Custom slots?
In my project I have to send pictures in the chat. I do not want to create a fork, but rather improve this project.
Thought it would probably be best to discuss how it can be implemented here first.
My first thought is that we can have two custom slots. One for pictures and one for attachments.
Suggested solution:
step 1 - Register that the user clicked the image button:

step 2 - the programmer does whatever he wants with the callback.
step 3 - Now it needs to be displayed in the chat..
Here is some possible suggestions/solutions:
- There are custom slots for different file types
- or no slots, but the json define how the "chat buble" will look like.
- Raw HTML components, with a <custom :rawHtml="<i>hi</i>">
- 10 different <custom1>, <custom2>, <custom3>... slots..
- Can you think of more options?
What are your thoughts on that? :-)
Hi, @martinandersen3d It's in my plans to implement such functionalities. However I'm quite busy, so I can't implement it yet (I plan to implement new functionalities at the end of this month). In my opinion, your suggestions are good and I'll follow it.
About step 3, I guess you can have two cases (two slot types):
- images (the chat displays a preview of the uploaded or received image)
- another file type (the chat displays an element with the filename and the file extension) (I think the most simple and generic solution is better because we can implement new functionalities after)
steps 1 and 2 are ok. Remember that probably the message object will have three new fields:
- messageType ('image', 'file' or 'text')
- contentUrl (if the message type is 'file' or 'image') and maybe
- contentSize (the file/image size in kb/mb)
Thanks for your feedback.
I completely agree with you.
If we implementing the messageType a fourth option could be "html". Then it is very very customizable.
My client is also talking about video chat in the future. Having the ability to insert raw html, would make it possible to do any custom styling and flexibility. Good for any features, that the client will come up with :D
So to add to your comment:
- messageType ('image', 'file', 'text', 'html')
- contentUrl (if the message type is 'file' or 'image') and maybe
- contentSize (the file/image size in kb/mb)
- contentHtml (for custom html)
The challenge is to create a extend-ability that serve many different purposes.. I can't tell if it should be slots or json, but with the Image and attachment, its really good start.
:on-image-upload :on-file-upload
@martinandersen3d Raw html would make it susceptible to XSS attacks, sure it's up to the server/dev to prevent this, but I'd rather not have accidental vulnerabilities, the message display should simply be slotted so the user can have control depending on the message type. Also the markup should be up to the vue component and not the server, v-html is a directive that's clearly stated as not best practice
I would also only add an option :on-file-upload type "function" if it's defined then display the attachment button (which should be slotted as are all other buttons), you will then be free to add two buttons rather than one for each file type
And another option for file types accepted, :file-types which could be defaulted to images (.jpg,.jpeg,.png,.gif)
And maybe another option for :multiple or only one file allowed
I would create a component FileUploadButton which would have a hidden file input and a button icon, inputs => file types, multiple, default slot for text. outputs => on file selected should send the FileList of the input
So the user can reuse this component if they need multiples buttons for different file types like you do
It's a straightforward dev (shouldn't take more than 1-2hour) so feel free to open a PR
Sounds good.
I do also agree on the raw html.
Links: I think if we make it possible to send links in the chat, then I would be able to forward any "video" chat features, via a link to another router in the application.
Maybe we could add it like: messageType ('image', 'file', 'text') contentUrl (if the message type is 'file' or 'image') and maybe contentSize (the file/image size in kb/mb) LinkUrl: ... LinkText: ... LinkImg:.. I don't know if there could/should be a image in the link, LinkId = Html Element ID LinkClass = Html Element Class participantCanPostClickableLinks:boolean = enable or disable if the user can send CLICKABLE links. Maybe the dev, dont want the user to be able to send clickable links, but at the same time the dev want to send application links to the chat.
I'm not sure what is the best way to do this, in a flexible way..
What do you think?
Links is another story. That would be a valid use case for using v-html however the message should be entirely html escaped first
Then it could be parsed with a regex and if you find a link add an tag for the link
When can also give control to users who knows what they are doing to v-html via the message type 'html'
I just came to mind that vue has what is called a dynamic component. Vue has an "is" tag that it can convert to an HTML element.
Here is the Vue code (html element type is defined in the "IS="):
<div is="a" href = "www .." class = "foo" style = "color: red">
anything inside component
</ div>
It will be converted to HTML:
<a href="www.." class="foo" style="color:red">
anything inside component
</a>
Vue does not allow "script" inside the tag, so safety is good.
I think this would be a good, secure and flexible solution.
You can see examples, and documentation here:
- https://codepen.io/martinandersen3d/pen/yLLrNYb
- https://stackoverflow.com/questions/41748934/how-to-create-dynamic-tag-based-on-props-with-vue-2
- https://vuejs.org/v2/guide/components.html#Dynamic-Components
Example:

This will not be helpful, Vue is not interpolated in v-html, and it's anyway the same as writtng an a tag, this feature is only useful when you need to change the vue component displayed based on some logic
I know how to display links without v-html
Instead of escaping it, just explode the text based on regex, parts that match url can be rendered inside an a, the rest in moustache
I think we misunderstand each other :D
I 100% agree that we can/should use a regex to make links, based on text that the user writes. That's not what I'm trying to explain :D : D
What I'm trying to do is: To create a solution that allows the external programmer to use the component to create the html messages to suit their needs. So make it as flexible as possible and still maintain the security that you talk about :-)
By using dynamic components, we can solve all of the above problems (- minus the regex), as well as enable other programmer to customize every chat messages look and feel, according to their own needs.
Here's what I'm trying to explain:

Now, the solution is not "perfect", since there is edge-cases that it will not solve, but there is a lot of stuff that it CAN do.
Does it make sense? :D
Okay I see what you're saying but this poses the problem I mentioned about the server having power over the tags used when this power should be left to vue alone via scoped slots, in the scoped slot you can check the message type and display absolutely any component you want rather than a runtime tag, so it's also more flexible, in fact so flexible that in your scoped slot you could define the solution you thought of and be free to use the message structure to customise the markup But it has the side effect of polluting the message structure => more memory and more data to send
I actually understand what you are trying to do now :D
I like it, its genius :D
So from the messageType, contentUrl, contentSize, external developers can create an unlimited numbers of different slots, where we can loop through and have different components with different properties. Thats really nice :D
Yes basically but not just those properties, since the entire message will be passed as a parameter to the scoped slot, you can use any property you want like this, giving you full control over the markup
<template #messageInner="tpl">
<!-- If type is text, do the default display, else display is customized -->
<MessageInner v-if="tpl.message.type == 'text'" v-bind="tpl.message"></MessageInner>
<span v-else-if="tpl.message.type == 'url'"><a :href="tpl.message.url" rel="noreferer noopener" target="_blank">{{tpl.message.content}}</a></span>
<span v-else-if="tpl.message.type == 'img'"><img :src="tpl.message.image" :alt="tpl.message.content"></span>
<!-- ... -->
</template>
If it's urgent, you can do a PR and I'll review it, else I can do it later this month
I would change the name of the component MessageDisplay to MessagesList for clarity and add a component MessageDisplay which will only contain the display markup PS: It's this part :
<div class="message-text"
:style="{background: !message.myself?colors.message.others.bg: colors.message.myself.bg, color: !message.myself?colors.message.others.text: colors.message.myself.text}">
<p v-if="!message.myself" class="message-username">{{getParticipantById(message.participantId).name}}</p>
<p v-else class="message-username">{{myself.name}}</p>
<p>{{message.content}}</p>
</div>
And a MessageTimestamp component
<div class="message-timestamp" :style="{'justify-content': message.myself?'flex-end':'baseline'}">
{{message.timestamp.format('LT')}}
<v-icon v-if="asyncMode && message.uploaded" name="check" base-class="icon-sent"/>
<div v-else-if="asyncMode" class="message-loading"></div>
</div>
So the scoped slot should be declared around MessageDisplay in MessageList, and another slot for the message timestamp
hi guys is anyone have the updated version with image upload feature. thanks
Curious about this image upload feature as well!
Anybody working on this? Else I will look into it, this month.. Anybody want to join? :-)
@Tofandel nice example :-D
@martinandersen3d I guess nobody is working on this feature. But I'll implement a way of display images on chat, as I said here #22.
Thanks ;-)
+1 .. it would be great if we can have images + files ... i will try to chip in ... been a while ... happy new year @MatheusrdSantos
I completely agree with you.
If we implementing the messageType a fourth option could be "html". Then it is very very customizable.
My client is also talking about video chat in the future. Having the ability to insert raw html, would make it possible to do any custom styling and flexibility. Good for any features, that the client will come up with :D
So to add to your comment:
- messageType ('image', 'file', 'text', 'html')
- contentUrl (if the message type is 'file' or 'image') and maybe
- contentSize (the file/image size in kb/mb)
- contentHtml (for custom html)
The challenge is to create a extend-ability that serve many different purposes.. I can't tell if it should be slots or json, but with the Image and attachment, its really good start.
if the html part is only about video embeds we can support oembed / graph data much like facebook and twitter but i thinks its a long way to go
:send-images="true" is enabling the image attatchment but
client.js:97 Error: Cannot linkify undefined - Invalid DOM Node type at linkifyElementHelper (vue-quick-chat.common.js:679) at linkifyElement (vue-quick-chat.common.js:742) at VueComponent.mounted (vue-quick-chat.common.js:16295)
when we try to attatch an image ... am i missing something
https://github.com/MatheusrdSantos/vue-quick-chat/pull/51 waiting for it get merged hope that would solve a small problem