Messages Component

    Messages Vue component represents Messages component.

    • - main Messages container
    • **f7-message** - single message element
    • **f7-messages-title** - single messages title element

    Messages Properties

    Messages Events

    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
    • **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

    Access To Messages Instance

    If you use automatic initalization to init Messages (with init:true prop) and need to use you can access its initialized instance by accessing **.f7Messages** component’s property.

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