
Messages Component
- Messages Components
- Messages Properties
- Messages Methods
- Messages Events
- Messages Slots
- Access To Messages Instance
- Examples
Messages Vue component represents Messages component.
Messages Components
There are following components included:
**f7-messages**- main Messages container**f7-message**- single message element**f7-messages-title**- single messages title element
Messages Properties
| Prop | Type | Default | Description |
|---|---|---|---|
| <f7-messages> properties | |||
| --- | --- | --- | --- |
| init | boolean | true | Initializes Messages component |
| new-messages-first | boolean | false | Enable if you want to use new messages on top, instead of having them on bottom |
| scroll-messages | boolean | true | Enable/disable messages autoscrolling when adding new message |
| scroll-messages-on-edge | boolean | true | If enabled then messages autoscrolling will happen only when user is on top/bottom of the messages view |
| <f7-message> properties | |||
| type | string | sent | Message type: sent (default) or received |
| text | string | Message text | |
| avatar | string | Message user’s avatar URL | |
| name | string | Message user’s name | |
| image | string | Message image URL | |
| header | string | Message header | |
| footer | string | Message footer | |
| text-header | string | Message text header | |
| text-footer | string | Message text footer | |
| first | boolean | false | Defines that the message is first in the conversation |
| last | boolean | false | Defines that the message is last in the conversation |
| tail | boolean | false | Defines that the message has visual “tail”. Usually last message in conversation |
| same-name | boolean | false | Defines that this message sender name is the same as on previous message |
| same-header | boolean | false | Defines that this message header text is the same as on previous message |
| same-footer | boolean | false | Defines that this message footer text is the same as on previous message |
| same-avatar | boolean | false | Defines that this message user’s avatar URL is the same as on previous message |
Messages Methods
| <f7-messages> methods | |
|---|---|
| .scroll(duration, position); | Scroll messages to top/bottom depending on newMessagesFirst parameter - duration - number scroll duration in ms - position - number scroll position in px |
| .showTyping(message); | Show typing message indicator - message - object - parameters of message to add |
| .hideTyping() | Hide typing message indicator |
Messages Events
| Event | Description |
|---|---|
| <f7-message> events | |
| --- | --- |
| click | Event will be triggered when user clicks on message bubble |
| click:name | Event will be triggered when user clicks on message user’s name |
| click:text | Event will be triggered when user clicks on message text |
| click:avatar | Event will be triggered when user clicks on message user’s avatar |
| click:header | Event will be triggered when user clicks on message header |
| click:footer | Event will be triggered when user clicks on message footer |
| click:bubble | Event will be triggered when user clicks on message bubble |
Messages Slots
Single message Vue component (<f7-message>) has additional slots for custom elements:
**default**- element will be inserted as a child of<div class="message-bubble">element in the end**start**- element will be inserted in the beginning and direct child of main message element<div class="message">**end**- element will be inserted in the end and direct child of main message element<div class="message">**content-start**- element will be inserted in the beginning and direct child of the<div class="message-content">element**content-end**- element will be inserted in the end and direct child of the<div class="message-content">element**bubble-start**- element will be inserted in the beginning and direct child of the<div class="message-bubble">element**bubble-end**- element will be inserted in the end and direct child of the<div class="message-bubble">element. Same as**default**slot
The following slots can be used inside of single message instead of same props if you need to pass there more complext layout:
**header**- element will be inserted in message header**footer**- element will be inserted in message footer**text**- element will be inserted in message text**name**- element will be inserted in message name**image**- element will be inserted in message image (supposed tp be an<img>element)**text-header**- element will be inserted in message text header**text-footer**- element will be inserted in message text footer
1. <f7-message
2. type="sent"
3. text="Hello World"
4. name="John Doe"
5. avatar="path/to/image.jpg"
6. >
7. <div slot="start">Start</div>
8. <div slot="end">End</div>
9. <div slot="content-start">Content Start</div>
10. <div slot="content-end">Content End</div>
11. <div slot="bubble-start">Bubble Start</div>
12. <div slot="bubble-end">Bubble End</div>
13. </f7-message>
15. <!-- Renders to: -->
17. <div class="message message-sent">
18. <div>Start</div>
19. <div class="message-avatar" style="background-image: url(path/to/image.jpg);"></div>
20. <div class="message-content">
21. <div>Content Start</div>
22. <div class="message-name">John Doe</div>
23. <div class="message-bubble">
24. <div>Bubble Start</div>
25. <div class="message-text">Hello World</div>
26. <div>Bubble End</div>
27. </div>
28. <div>Content End</div>
29. </div>
30. <div>End</div>
31. </div>
Access To Messages Instance
If you use automatic initalization to init Messages (with init:true prop) and need to use Messages API you can access its initialized instance by accessing **.f7Messages** component’s property.
Examples
Here is how the full example of Messages page where it can be used together with Messagebar:
1. <template>
2. <f7-page>
3. <f7-navbar title="Messsages"></f7-navbar>
5. <f7-messagebar
6. :placeholder="placeholder"
7. ref="messagebar"
8. :attachments-visible="attachmentsVisible"
9. :sheet-visible="sheetVisible"
10. >
11. <f7-link
12. icon-ios="f7:camera_fill"
13. icon-aurora="f7:camera_fill"
14. icon-md="material:camera_alt"
15. slot="inner-start"
16. @click="sheetVisible = !sheetVisible"
17. ></f7-link>
18. <f7-link
19. icon-ios="f7:arrow_up_fill"
20. icon-aurora="f7:arrow_up_fill"
21. icon-md="material:send"
22. slot="inner-end"
23. @click="sendMessage"
24. ></f7-link>
25. <f7-messagebar-attachments>
26. <f7-messagebar-attachment
27. v-for="(image, index) in attachments"
28. :key="index"
29. :image="image"
30. @attachment:delete="deleteAttachment(image)"
31. ></f7-messagebar-attachment>
32. </f7-messagebar-attachments>
33. <f7-messagebar-sheet>
34. <f7-messagebar-sheet-image
35. v-for="(image, index) in images"
36. :key="index"
37. :image="image"
38. :checked="attachments.indexOf(image) >= 0"
39. @change="handleAttachment"
40. ></f7-messagebar-sheet-image>
41. </f7-messagebar-sheet>
42. </f7-messagebar>
44. <f7-messages ref="messages">
45. <f7-messages-title><b>Sunday, Feb 9,</b> 12:58</f7-messages-title>
46. <f7-message
47. v-for="(message, index) in messagesData"
48. :key="index"
49. :type="message.type"
50. :image="message.image"
51. :name="message.name"
52. :avatar="message.avatar"
53. :first="isFirstMessage(message, index)"
54. :last="isLastMessage(message, index)"
55. :tail="isTailMessage(message, index)"
56. >
57. <span slot="text" v-if="message.text" v-html="message.text"></span>
58. </f7-message>
59. <f7-message v-if="typingMessage"
60. type="received"
61. :typing="true"
62. :first="true"
63. :last="true"
64. :tail="true"
65. :header="`${typingMessage.name} is typing`"
66. :avatar="typingMessage.avatar"
67. ></f7-message>
68. </f7-messages>
69. </f7-page>
70. </template>
71. <script>
72. export default {
73. data() {
74. return {
75. attachments: [],
76. sheetVisible: false,
77. typingMessage: null,
78. messagesData: [
79. {
80. type: 'sent',
81. text: 'Hi, Kate',
82. },
83. {
84. type: 'sent',
85. text: 'How are you?',
86. },
87. {
88. name: 'Kate',
89. type: 'received',
90. text: 'Hi, I am good!',
91. avatar: 'https://cdn.framework7.io/placeholder/people-100x100-9.jpg',
92. },
93. {
94. name: 'Blue Ninja',
95. type: 'received',
96. text: 'Hi there, I am also fine, thanks! And how are you?',
97. avatar: 'https://cdn.framework7.io/placeholder/people-100x100-7.jpg',
98. },
99. {
100. type: 'sent',
101. text: 'Hey, Blue Ninja! Glad to see you ;)',
102. },
103. {
104. type: 'sent',
105. text: 'Hey, look, cutest kitten ever!',
106. },
107. {
108. type: 'sent',
109. image: 'https://cdn.framework7.io/placeholder/cats-200x260-4.jpg',
111. },
112. {
113. name: 'Kate',
114. type: 'received',
115. text: 'Nice!',
116. avatar: 'https://cdn.framework7.io/placeholder/people-100x100-9.jpg',
117. },
118. {
119. name: 'Kate',
120. type: 'received',
121. text: 'Like it very much!',
122. avatar: 'https://cdn.framework7.io/placeholder/people-100x100-9.jpg',
123. },
124. {
125. name: 'Blue Ninja',
126. type: 'received',
127. text: 'Awesome!',
128. avatar: 'https://cdn.framework7.io/placeholder/people-100x100-7.jpg',
129. },
130. ],
131. images: [
132. 'https://cdn.framework7.io/placeholder/cats-300x300-1.jpg',
133. 'https://cdn.framework7.io/placeholder/cats-200x300-2.jpg',
134. 'https://cdn.framework7.io/placeholder/cats-400x300-3.jpg',
135. 'https://cdn.framework7.io/placeholder/cats-300x150-4.jpg',
136. 'https://cdn.framework7.io/placeholder/cats-150x300-5.jpg',
137. 'https://cdn.framework7.io/placeholder/cats-300x300-6.jpg',
138. 'https://cdn.framework7.io/placeholder/cats-300x300-7.jpg',
139. 'https://cdn.framework7.io/placeholder/cats-200x300-8.jpg',
140. 'https://cdn.framework7.io/placeholder/cats-400x300-9.jpg',
141. 'https://cdn.framework7.io/placeholder/cats-300x150-10.jpg',
142. ],
143. people: [
144. {
145. name: 'Kate Johnson',
146. avatar: 'https://cdn.framework7.io/placeholder/people-100x100-9.jpg',
147. },
148. {
149. name: 'Blue Ninja',
150. avatar: 'https://cdn.framework7.io/placeholder/people-100x100-7.jpg',
151. },
152. ],
153. answers: [
154. 'Yes!',
155. 'No',
156. 'Hm...',
157. 'I am not sure',
158. 'And what about you?',
159. 'May be ;)',
160. 'Lorem ipsum dolor sit amet, consectetur',
161. 'What?',
162. 'Are you sure?',
163. 'Of course',
164. 'Need to think about it',
165. 'Amazing!!!',
166. ],
167. responseInProgress: false,
168. };
169. },
170. computed: {
171. attachmentsVisible() {
172. const self = this;
173. return self.attachments.length > 0;
174. },
175. placeholder() {
176. const self = this;
177. return self.attachments.length > 0 ? 'Add comment or Send' : 'Message';
178. },
179. },
180. mounted() {
181. const self = this;
182. self.$f7ready(() => {
183. self.messagebar = self.$refs.messagebar.f7Messagebar;
184. self.messages = self.$refs.messages.f7Messages;
185. });
186. },
187. methods: {
188. isFirstMessage(message, index) {
189. const self = this;
190. const previousMessage = self.messagesData[index - 1];
191. if (message.isTitle) return false;
192. if (!previousMessage || previousMessage.type !== message.type || previousMessage.name !== message.name) return true;
193. return false;
194. },
195. isLastMessage(message, index) {
196. const self = this;
197. const nextMessage = self.messagesData[index + 1];
198. if (message.isTitle) return false;
199. if (!nextMessage || nextMessage.type !== message.type || nextMessage.name !== message.name) return true;
200. return false;
201. },
202. isTailMessage(message, index) {
203. const self = this;
204. const nextMessage = self.messagesData[index + 1];
205. if (message.isTitle) return false;
206. if (!nextMessage || nextMessage.type !== message.type || nextMessage.name !== message.name) return true;
207. return false;
208. },
209. deleteAttachment(image) {
210. const self = this;
211. const index = self.attachments.indexOf(image);
212. self.attachments.splice(index, 1)[0]; // eslint-disable-line
213. },
214. handleAttachment(e) {
215. const self = this;
216. const index = self.$$(e.target).parents('label.checkbox').index();
217. const image = self.images[index];
218. if (e.target.checked) {
219. // Add to attachments
220. self.attachments.unshift(image);
221. } else {
222. // Remove from attachments
223. self.attachments.splice(self.attachments.indexOf(image), 1);
224. }
225. },
226. sendMessage() {
227. const self = this;
228. const text = self.messagebar.getValue().replace(/\n/g, '<br>').trim();
229. const messagesToSend = [];
230. self.attachments.forEach((attachment) => {
231. messagesToSend.push({
232. image: attachment,
233. });
234. });
235. if (text.trim().length) {
236. messagesToSend.push({
237. text,
238. });
239. }
240. if (messagesToSend.length === 0) {
241. return;
242. }
244. // Reset attachments
245. self.attachments = [];
246. // Hide sheet
247. self.sheetVisible = false;
248. // Clear area
249. self.messagebar.clear();
250. // Focus area
251. if (text.length) self.messagebar.focus();
252. // Send message
253. self.messagesData.push(...messagesToSend);
255. // Mock response
256. if (self.responseInProgress) return;
257. self.responseInProgress = true;
258. setTimeout(() => {
259. const answer = self.answers[Math.floor(Math.random() * self.answers.length)];
260. const person = self.people[Math.floor(Math.random() * self.people.length)];
261. self.typingMessage = {
262. name: person.name,
263. avatar: person.avatar,
264. };
265. setTimeout(() => {
266. self.messagesData.push({
267. text: answer,
268. type: 'received',
269. name: person.name,
270. avatar: person.avatar,
271. });
272. self.typingMessage = null;
273. self.responseInProgress = false;
274. }, 4000);
275. }, 1000);
276. },
277. },
278. };
279. </script>
