
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-md="material:camera_alt"
14. slot="inner-start"
15. @click="sheetVisible = !sheetVisible"
16. ></f7-link>
17. <f7-link
18. icon-ios="f7:arrow_up_fill"
19. icon-md="material:send"
20. slot="inner-end"
21. @click="sendMessage"
22. ></f7-link>
23. <f7-messagebar-attachments>
24. <f7-messagebar-attachment
25. v-for="(image, index) in attachments"
26. :key="index"
27. :image="image"
28. @attachment:delete="deleteAttachment(image)"
29. ></f7-messagebar-attachment>
30. </f7-messagebar-attachments>
31. <f7-messagebar-sheet>
32. <f7-messagebar-sheet-image
33. v-for="(image, index) in images"
34. :key="index"
35. :image="image"
36. :checked="attachments.indexOf(image) >= 0"
37. @change="handleAttachment"
38. ></f7-messagebar-sheet-image>
39. </f7-messagebar-sheet>
40. </f7-messagebar>
42. <f7-messages ref="messages">
43. <f7-messages-title><b>Sunday, Feb 9,</b> 12:58</f7-messages-title>
44. <f7-message
45. v-for="(message, index) in messagesData"
46. :key="index"
47. :type="message.type"
48. :image="message.image"
49. :name="message.name"
50. :avatar="message.avatar"
51. :first="isFirstMessage(message, index)"
52. :last="isLastMessage(message, index)"
53. :tail="isTailMessage(message, index)"
54. >
55. <span slot="text" v-if="message.text" v-html="message.text"></span>
56. </f7-message>
57. <f7-message v-if="typingMessage"
58. type="received"
59. :typing="true"
60. :first="true"
61. :last="true"
62. :tail="true"
63. :header="`${typingMessage.name} is typing`"
64. :avatar="typingMessage.avatar"
65. ></f7-message>
66. </f7-messages>
67. </f7-page>
68. </template>
69. <script>
70. export default {
71. data() {
72. return {
73. attachments: [],
74. sheetVisible: false,
75. typingMessage: null,
76. messagesData: [
77. {
78. type: 'sent',
79. text: 'Hi, Kate',
80. },
81. {
82. type: 'sent',
83. text: 'How are you?',
84. },
85. {
86. name: 'Kate',
87. type: 'received',
88. text: 'Hi, I am good!',
89. avatar: 'http://lorempixel.com/100/100/people/9',
90. },
91. {
92. name: 'Blue Ninja',
93. type: 'received',
94. text: 'Hi there, I am also fine, thanks! And how are you?',
95. avatar: 'http://lorempixel.com/100/100/people/7',
96. },
97. {
98. type: 'sent',
99. text: 'Hey, Blue Ninja! Glad to see you ;)',
100. },
101. {
102. type: 'sent',
103. text: 'Hey, look, cutest kitten ever!',
104. },
105. {
106. type: 'sent',
107. image: 'http://lorempixel.com/200/260/cats/4/',
109. },
110. {
111. name: 'Kate',
112. type: 'received',
113. text: 'Nice!',
114. avatar: 'http://lorempixel.com/100/100/people/9',
115. },
116. {
117. name: 'Kate',
118. type: 'received',
119. text: 'Like it very much!',
120. avatar: 'http://lorempixel.com/100/100/people/9',
121. },
122. {
123. name: 'Blue Ninja',
124. type: 'received',
125. text: 'Awesome!',
126. avatar: 'http://lorempixel.com/100/100/people/7',
127. },
128. ],
129. images: [
130. 'http://lorempixel.com/300/300/cats/1/',
131. 'http://lorempixel.com/200/300/cats/2/',
132. 'http://lorempixel.com/400/300/cats/3/',
133. 'http://lorempixel.com/300/150/cats/4/',
134. 'http://lorempixel.com/150/300/cats/5/',
135. 'http://lorempixel.com/300/300/cats/6/',
136. 'http://lorempixel.com/300/300/cats/7/',
137. 'http://lorempixel.com/200/300/cats/8/',
138. 'http://lorempixel.com/400/300/cats/9/',
139. 'http://lorempixel.com/300/150/cats/10/',
140. ],
141. people: [
142. {
143. name: 'Kate Johnson',
144. avatar: 'http://lorempixel.com/100/100/people/9',
145. },
146. {
147. name: 'Blue Ninja',
148. avatar: 'http://lorempixel.com/100/100/people/7',
149. },
150. ],
151. answers: [
152. 'Yes!',
153. 'No',
154. 'Hm...',
155. 'I am not sure',
156. 'And what about you?',
157. 'May be ;)',
158. 'Lorem ipsum dolor sit amet, consectetur',
159. 'What?',
160. 'Are you sure?',
161. 'Of course',
162. 'Need to think about it',
163. 'Amazing!!!',
164. ],
165. responseInProgress: false,
166. };
167. },
168. computed: {
169. attachmentsVisible() {
170. const self = this;
171. return self.attachments.length > 0;
172. },
173. placeholder() {
174. const self = this;
175. return self.attachments.length > 0 ? 'Add comment or Send' : 'Message';
176. },
177. },
178. mounted() {
179. const self = this;
180. self.$f7ready(() => {
181. self.messagebar = self.$refs.messagebar.f7Messagebar;
182. self.messages = self.$refs.messages.f7Messages;
183. });
184. },
185. methods: {
186. isFirstMessage(message, index) {
187. const self = this;
188. const previousMessage = self.messagesData[index - 1];
189. if (message.isTitle) return false;
190. if (!previousMessage || previousMessage.type !== message.type || previousMessage.name !== message.name) return true;
191. return false;
192. },
193. isLastMessage(message, index) {
194. const self = this;
195. const nextMessage = self.messagesData[index + 1];
196. if (message.isTitle) return false;
197. if (!nextMessage || nextMessage.type !== message.type || nextMessage.name !== message.name) return true;
198. return false;
199. },
200. isTailMessage(message, index) {
201. const self = this;
202. const nextMessage = self.messagesData[index + 1];
203. if (message.isTitle) return false;
204. if (!nextMessage || nextMessage.type !== message.type || nextMessage.name !== message.name) return true;
205. return false;
206. },
207. deleteAttachment(image) {
208. const self = this;
209. const index = self.attachments.indexOf(image);
210. self.attachments.splice(index, 1)[0]; // eslint-disable-line
211. },
212. handleAttachment(e) {
213. const self = this;
214. const index = self.$$(e.target).parents('label.checkbox').index();
215. const image = self.images[index];
216. if (e.target.checked) {
217. // Add to attachments
218. self.attachments.unshift(image);
219. } else {
220. // Remove from attachments
221. self.attachments.splice(self.attachments.indexOf(image), 1);
222. }
223. },
224. sendMessage() {
225. const self = this;
226. const text = self.messagebar.getValue().replace(/\n/g, '<br>').trim();
227. const messagesToSend = [];
228. self.attachments.forEach((attachment) => {
229. messagesToSend.push({
230. image: attachment,
231. });
232. });
233. if (text.trim().length) {
234. messagesToSend.push({
235. text,
236. });
237. }
238. if (messagesToSend.length === 0) {
239. return;
240. }
242. // Reset attachments
243. self.attachments = [];
244. // Hide sheet
245. self.sheetVisible = false;
246. // Clear area
247. self.messagebar.clear();
248. // Focus area
249. if (text.length) self.messagebar.focus();
250. // Send message
251. self.messagesData.push(...messagesToSend);
253. // Mock response
254. if (self.responseInProgress) return;
255. self.responseInProgress = true;
256. setTimeout(() => {
257. const answer = self.answers[Math.floor(Math.random() * self.answers.length)];
258. const person = self.people[Math.floor(Math.random() * self.people.length)];
259. self.typingMessage = {
260. name: person.name,
261. avatar: person.avatar,
262. };
263. setTimeout(() => {
264. self.messagesData.push({
265. text: answer,
266. type: 'received',
267. name: person.name,
268. avatar: person.avatar,
269. });
270. self.typingMessage = null;
271. self.responseInProgress = false;
272. }, 4000);
273. }, 1000);
274. },
275. },
276. };
277. </script>
