Messages Component

    Messages React component represents Messages component.

    • / **F7Messages** - main Messages container
    • **Message** / **F7Message** - single message element
    • **MessagesTitle** / **F7MessagesTitle** - single messages title element

    Messages Properties

    Messages Events

    Single message React component (<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 Messages API you can access its initialized instance by accessing **.f7Messages** component’s property.

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