
Messagebar React Component
Messagebar React component represents Framework7’s Messagebar component.
Messagebar Components
There are following components included:
**Messagebar**/**F7Messagebar**- main messagebar element**MessagebarSheet**/**F7MessagebarSheet**- messagebar sheet element**MessagebarSheetImage**/**F7MessagebarSheetImage**- messagebar sheet image item**MessagebarSheetItem**/**F7MessagebarSheetItem**- messagebar sheet item**MessagebarAttachments**/**F7MessagebarAttachments**- messagebar attachments element**MessagebarAttachment**/**F7MessagebarAttachment**- single messagebar attachment element

Messagebar Properties
| Prop | Type | Default | Description |
|---|---|---|---|
| <Messagebar> properties | |||
| --- | --- | --- | --- |
| init | boolean | true | Initializes Messagebar |
| name | string | Textarea “name” attribute | |
| textareaId | string number | Textarea “id” attribute | |
| placeholder | string | Message | Textarea placeholder text |
| value | string number | Textarea value | |
| readonly | boolean | false | Sets “readonly” textarea attribute |
| disabled | boolean | false | Sets “disbled” textarea attribute |
| sendLink | string | Enables Send link and specifies its text. This property will be ignored in case you use send-link slot |
|
| maxHeight | number | Defines resizeable textarea max height | |
| resizable | bolean | true | Enables resizeable textarea |
| sheetVisible | boolean | false | Makes messagebar sheet visible/active |
| attachmentsVisible | boolean | false | Makes messagebar attachments visible/active |
| resizePage | boolean | true | When enabled, it will resize messages page when messagebar textarea size changed |
| <MessagebarSheetImage> properties | |||
| image | string | Sheet image URL | |
| checked | boolean | false | Indicates whether this sheet image-item is checked or not |
| <MessagebarAttachment> properties | |||
| image | string | Attachment image URL | |
| deletable | boolean | true | Defines whether the attachment is deletable or not. In case of deletable the additional delete button will be rendered |
Messagebar Methods
| <Messagebar> methods | |
|---|---|
| .clear() | Clear textarea and update/reset its size |
| .setValue(newValue) | Set messagebar textarea value/text |
| .getValue() | Return messagebar textarea value |
| .resize() | Force Messagebar to resize messages page depending on messagebar height/size |
| .focus() | Focus messagebar textarea |
| .blur() | Remove focus from messagebar textarea |
Messagebar Events
| Event | Arguments | Description |
|---|---|---|
| <Messagebar> events | ||
| --- | --- | --- |
| change | (event) | Event will be triggered when “change” event occurs on messagebar textarea element |
| input | (event) | Event will be triggered when “input” event occurs on messagebar textarea element |
| focus | (event) | Event will be triggered when “focus” event occurs on messagebar textarea element |
| blur | (event) | Event will be triggered when “blur” event occurs on messagebar textarea element |
| submit send | (value, clear) | Event will be triggered when user clicks on messagebar “send link” |
| <MessagebarSheetImage> events | ||
| change | (event) | Event will be triggered on sheet item checkbox change |
| <MessagebarAttachment> events | ||
| attachmentClick | (event) | Event will be triggered on attachment click |
| attachmentDelete | (event) | Event will be triggered on attachment delete button click |
Messagebar Slots
Messagebar React component has additional slots for custom elements:
**default**- element will be inserted in the end of<div class="toolbar-inner">. element**before-area**- element will be inserted right before textarea. Messagebar attachments go here**after-area**- element will be inserted right after textarea**send-link**- element will be inserted inside of send link**before-inner**- element will be inserted right before<div class="toolbar-inner">. element**after-inner**- element will be inserted right after<div class="toolbar-inner">. element. Messagebar sheet goes here**inner-start**- element will be inserted in the beginning of<div class="toolbar-inner">. element**inner-end**- element will be inserted in the end of<div class="toolbar-inner">. element. Same asdefaultslot
1. <Messagebar placeholder="Message" onSubmit="this.onSubmit">
2. <div slot="before-inner">Before inner</div>
3. <div slot="after-inner">After inner</div>
4. <div slot="before-area">Before textarea</div>
5. <div slot="after-area">After textarea</div>
6. <Icon ios="f7:arrow_up_fill" aurora="f7:arrow_up_fill" md="material:send" slot="send-link"></Icon>
7. <div>Default slot</div>
8. </Messagebar>
Renders to:
1. <div class="toolbar messagebar">
2. <div>Before inner</div>
3. <div class="toolbar-inner">
4. <div class="messagebar-area">
5. <div>Before textarea</div>
6. <textarea placeholder="Message"></textarea>
7. <div>After textarea</div>
8. </div>
9. <a href="#" class="link"><i class="icon f7-icons">arrow_up_fill</i></a>
10. <div>Default slot</div>
11. </div>
12. <div>After inner</div>
13. </div>
Access To Messagebar Instance
If you use automatic initalization to init Messagebar (with init={true} prop) and need to use its Methods and Properties you can access its initialized instance by accessing **.f7Messagebar** component’s property.
Examples
Here is how the full example of Messages page where it can be used together with Messages:
1. export default class extends React.Component {
2. constructor(props) {
3. super(props);
5. this.state = {
6. attachments: [],
7. sheetVisible: false,
8. typingMessage: null,
9. messagesData: [
10. {
11. type: 'sent',
12. text: 'Hi, Kate',
13. },
14. {
15. type: 'sent',
16. text: 'How are you?',
17. },
18. {
19. name: 'Kate',
20. type: 'received',
21. text: 'Hi, I am good!',
22. avatar: 'https://cdn.framework7.io/placeholder/people-100x100-9.jpg',
23. },
24. {
25. name: 'Blue Ninja',
26. type: 'received',
27. text: 'Hi there, I am also fine, thanks! And how are you?',
28. avatar: 'https://cdn.framework7.io/placeholder/people-100x100-7.jpg',
29. },
30. {
31. type: 'sent',
32. text: 'Hey, Blue Ninja! Glad to see you ;)',
33. },
34. {
35. type: 'sent',
36. text: 'Hey, look, cutest kitten ever!',
37. },
38. {
39. type: 'sent',
40. image: 'https://cdn.framework7.io/placeholder/cats-200x260-4.jpg',
42. },
43. {
44. name: 'Kate',
45. type: 'received',
46. text: 'Nice!',
47. avatar: 'https://cdn.framework7.io/placeholder/people-100x100-9.jpg',
48. },
49. {
50. name: 'Kate',
51. type: 'received',
52. text: 'Like it very much!',
53. avatar: 'https://cdn.framework7.io/placeholder/people-100x100-9.jpg',
54. },
55. {
56. name: 'Blue Ninja',
57. type: 'received',
58. text: 'Awesome!',
59. avatar: 'https://cdn.framework7.io/placeholder/people-100x100-7.jpg',
60. },
61. ],
62. images: [
63. 'https://cdn.framework7.io/placeholder/cats-300x300-1.jpg',
64. 'https://cdn.framework7.io/placeholder/cats-200x300-2.jpg',
65. 'https://cdn.framework7.io/placeholder/cats-400x300-3.jpg',
66. 'https://cdn.framework7.io/placeholder/cats-300x150-4.jpg',
67. 'https://cdn.framework7.io/placeholder/cats-150x300-5.jpg',
68. 'https://cdn.framework7.io/placeholder/cats-300x300-6.jpg',
69. 'https://cdn.framework7.io/placeholder/cats-300x300-7.jpg',
70. 'https://cdn.framework7.io/placeholder/cats-200x300-8.jpg',
71. 'https://cdn.framework7.io/placeholder/cats-400x300-9.jpg',
72. 'https://cdn.framework7.io/placeholder/cats-300x150-10.jpg',
73. ],
74. people: [
75. {
76. name: 'Kate Johnson',
77. avatar: 'https://cdn.framework7.io/placeholder/people-100x100-9.jpg',
78. },
79. {
80. name: 'Blue Ninja',
81. avatar: 'https://cdn.framework7.io/placeholder/people-100x100-7.jpg',
82. },
83. ],
84. answers: [
85. 'Yes!',
86. 'No',
87. 'Hm...',
88. 'I am not sure',
89. 'And what about you?',
90. 'May be ;)',
91. 'Lorem ipsum dolor sit amet, consectetur',
92. 'What?',
93. 'Are you sure?',
94. 'Of course',
95. 'Need to think about it',
96. 'Amazing!!!',
97. ],
98. responseInProgress: false,
99. }
100. }
101. render() {
102. return (
103. <Page>
104. <Navbar title="Messsages"></Navbar>
106. <Messagebar
107. placeholder={this.placeholder}
108. ref={(el) => {this.messagebarComponent = el}}
109. attachmentsVisible={this.attachmentsVisible}
110. sheetVisible={this.state.sheetVisible}
111. >
112. <Link
113. iconIos="f7:camera_fill"
114. iconAurora="f7:camera_fill"
115. iconMd="material:camera_alt"
116. slot="inner-start"
117. onClick={() => {this.setState({sheetVisible: !this.state.sheetVisible})}}
118. ></Link>
119. <Link
120. iconIos="f7:arrow_up_fill"
121. iconAurora="f7:arrow_up_fill"
122. iconMd="material:send"
123. slot="inner-end"
124. onClick={this.sendMessage.bind(this)}
125. ></Link>
126. <MessagebarAttachments>
127. {this.state.attachments.map((image, index) => (
128. <MessagebarAttachment
129. key={index}
130. image={image}
131. onAttachmentDelete={() => this.deleteAttachment(image)}
132. ></MessagebarAttachment>
133. ))}
134. </MessagebarAttachments>
135. <MessagebarSheet>
136. {this.state.images.map((image, index) => (
137. <MessagebarSheetImage
138. key={index}
139. image={image}
140. checked={this.state.attachments.indexOf(image) >= 0}
141. onChange={this.handleAttachment.bind(this)}
142. ></MessagebarSheetImage>
143. ))}
144. </MessagebarSheet>
145. </Messagebar>
147. <Messages ref={(el) => {this.messagesComponent = el}}>
148. <MessagesTitle><b>Sunday, Feb 9,</b> 12:58</MessagesTitle>
150. {this.state.messagesData.map((message, index) => (
151. <Message
152. key={index}
153. type={message.type}
154. image={message.image}
155. name={message.name}
156. avatar={message.avatar}
157. first={this.isFirstMessage(message, index)}
158. last={this.isLastMessage(message, index)}
159. tail={this.isTailMessage(message, index)}
160. >
161. {message.text && (
162. <span slot="text" dangerouslySetInnerHTML={{__html: message.text}} />
163. )}
164. </Message>
165. ))}
166. {this.state.typingMessage && (
167. <Message
168. type="received"
169. typing={true}
170. first={true}
171. last={true}
172. tail={true}
173. header={`${this.state.typingMessage.name} is typing`}
174. avatar={this.state.typingMessage.avatar}
175. ></Message>
176. )}
177. </Messages>
178. </Page>
179. )
180. }
182. get attachmentsVisible() {
183. const self = this;
184. return self.state.attachments.length > 0;
185. }
186. get placeholder() {
187. const self = this;
188. return self.state.attachments.length > 0 ? 'Add comment or Send' : 'Message';
189. }
190. componentDidMount() {
191. const self = this;
192. self.$f7ready(() => {
193. self.messagebar = self.messagebarComponent.f7Messagebar;
194. self.messages = self.messagesComponent.f7Messages;
195. });
196. }
197. isFirstMessage(message, index) {
198. const self = this;
199. const previousMessage = self.state.messagesData[index - 1];
200. if (message.isTitle) return false;
201. if (!previousMessage || previousMessage.type !== message.type || previousMessage.name !== message.name) return true;
202. return false;
203. }
204. isLastMessage(message, index) {
205. const self = this;
206. const nextMessage = self.state.messagesData[index + 1];
207. if (message.isTitle) return false;
208. if (!nextMessage || nextMessage.type !== message.type || nextMessage.name !== message.name) return true;
209. return false;
210. }
211. isTailMessage(message, index) {
212. const self = this;
213. const nextMessage = self.state.messagesData[index + 1];
214. if (message.isTitle) return false;
215. if (!nextMessage || nextMessage.type !== message.type || nextMessage.name !== message.name) return true;
216. return false;
217. }
218. deleteAttachment(image) {
219. const self = this;
220. const attachments = self.state.attachments;
221. const index = attachments.indexOf(image);
222. attachments.splice(index, 1);
223. self.setState({ attachments });
224. }
225. handleAttachment(e) {
226. const self = this;
227. const attachments = self.state.attachments;
228. const index = self.$$(e.target).parents('label.checkbox').index();
229. const image = self.state.images[index];
230. if (e.target.checked) {
231. // Add to attachments
232. attachments.unshift(image);
233. } else {
234. // Remove from attachments
235. attachments.splice(attachments.indexOf(image), 1);
236. }
237. self.setState({ attachments });
238. }
239. sendMessage() {
240. const self = this;
241. const text = self.messagebar.getValue().replace(/\n/g, '<br>').trim();
242. const messagesToSend = [];
243. self.state.attachments.forEach((attachment) => {
244. messagesToSend.push({
245. image: attachment,
246. });
247. });
248. if (text.trim().length) {
249. messagesToSend.push({
250. text,
251. });
252. }
253. if (messagesToSend.length === 0) {
254. return;
255. }
257. self.setState({
258. // Reset attachments
259. attachments: [],
260. // Hide sheet
261. sheetVisible: false,
262. // Send message
263. messagesData: [...self.state.messagesData, ...messagesToSend],
264. });
265. self.messagebar.clear();
267. // Focus area
268. if (text.length) self.messagebar.focus();
270. // Mock response
271. if (self.state.responseInProgress) return;
272. self.setState({
273. responseInProgress: true,
274. })
275. setTimeout(() => {
276. const answer = self.state.answers[Math.floor(Math.random() * self.state.answers.length)];
277. const person = self.state.people[Math.floor(Math.random() * self.state.people.length)];
278. self.setState({
279. typingMessage: {
280. name: person.name,
281. avatar: person.avatar,
282. },
283. });
284. setTimeout(() => {
285. self.setState({
286. messagesData: [...self.state.messagesData, {
287. text: answer,
288. type: 'received',
289. name: person.name,
290. avatar: person.avatar,
291. }],
292. typingMessage: null,
293. responseInProgress: false,
294. });
295. }, 4000);
296. }, 1000);
297. }
298. };
