
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" 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: 'http://lorempixel.com/100/100/people/9',
23. },
24. {
25. name: 'Blue Ninja',
26. type: 'received',
27. text: 'Hi there, I am also fine, thanks! And how are you?',
28. avatar: 'http://lorempixel.com/100/100/people/7',
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: 'http://lorempixel.com/200/260/cats/4/',
42. },
43. {
44. name: 'Kate',
45. type: 'received',
46. text: 'Nice!',
47. avatar: 'http://lorempixel.com/100/100/people/9',
48. },
49. {
50. name: 'Kate',
51. type: 'received',
52. text: 'Like it very much!',
53. avatar: 'http://lorempixel.com/100/100/people/9',
54. },
55. {
56. name: 'Blue Ninja',
57. type: 'received',
58. text: 'Awesome!',
59. avatar: 'http://lorempixel.com/100/100/people/7',
60. },
61. ],
62. images: [
63. 'http://lorempixel.com/300/300/cats/1/',
64. 'http://lorempixel.com/200/300/cats/2/',
65. 'http://lorempixel.com/400/300/cats/3/',
66. 'http://lorempixel.com/300/150/cats/4/',
67. 'http://lorempixel.com/150/300/cats/5/',
68. 'http://lorempixel.com/300/300/cats/6/',
69. 'http://lorempixel.com/300/300/cats/7/',
70. 'http://lorempixel.com/200/300/cats/8/',
71. 'http://lorempixel.com/400/300/cats/9/',
72. 'http://lorempixel.com/300/150/cats/10/',
73. ],
74. people: [
75. {
76. name: 'Kate Johnson',
77. avatar: 'http://lorempixel.com/100/100/people/9',
78. },
79. {
80. name: 'Blue Ninja',
81. avatar: 'http://lorempixel.com/100/100/people/7',
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. iconMd="material:camera_alt"
115. slot="inner-start"
116. onClick={() => {this.setState({sheetVisible: !this.state.sheetVisible})}}
117. ></Link>
118. <Link
119. iconIos="f7:arrow_up_fill"
120. iconMd="material:send"
121. slot="inner-end"
122. onClick={this.sendMessage.bind(this)}
123. ></Link>
124. <MessagebarAttachments>
125. {this.state.attachments.map((image, index) => (
126. <MessagebarAttachment
127. key={index}
128. image={image}
129. onAttachmentDelete={() => this.deleteAttachment(image)}
130. ></MessagebarAttachment>
131. ))}
132. </MessagebarAttachments>
133. <MessagebarSheet>
134. {this.state.images.map((image, index) => (
135. <MessagebarSheetImage
136. key={index}
137. image={image}
138. checked={this.state.attachments.indexOf(image) >= 0}
139. onChange={this.handleAttachment.bind(this)}
140. ></MessagebarSheetImage>
141. ))}
142. </MessagebarSheet>
143. </Messagebar>
145. <Messages ref={(el) => {this.messagesComponent = el}}>
146. <MessagesTitle><b>Sunday, Feb 9,</b> 12:58</MessagesTitle>
148. {this.state.messagesData.map((message, index) => (
149. <Message
150. key={index}
151. type={message.type}
152. image={message.image}
153. name={message.name}
154. avatar={message.avatar}
155. first={this.isFirstMessage(message, index)}
156. last={this.isLastMessage(message, index)}
157. tail={this.isTailMessage(message, index)}
158. >
159. {message.text && (
160. <span slot="text" dangerouslySetInnerHTML={{__html: message.text}} />
161. )}
162. </Message>
163. ))}
164. {this.state.typingMessage && (
165. <Message
166. type="received"
167. typing={true}
168. first={true}
169. last={true}
170. tail={true}
171. header={`${this.state.typingMessage.name} is typing`}
172. avatar={this.state.typingMessage.avatar}
173. ></Message>
174. )}
175. </Messages>
176. </Page>
177. )
178. }
180. get attachmentsVisible() {
181. const self = this;
182. return self.state.attachments.length > 0;
183. }
184. get placeholder() {
185. const self = this;
186. return self.state.attachments.length > 0 ? 'Add comment or Send' : 'Message';
187. }
188. componentDidMount() {
189. const self = this;
190. self.$f7ready(() => {
191. self.messagebar = self.messagebarComponent.f7Messagebar;
192. self.messages = self.messagesComponent.f7Messages;
193. });
194. }
195. isFirstMessage(message, index) {
196. const self = this;
197. const previousMessage = self.state.messagesData[index - 1];
198. if (message.isTitle) return false;
199. if (!previousMessage || previousMessage.type !== message.type || previousMessage.name !== message.name) return true;
200. return false;
201. }
202. isLastMessage(message, index) {
203. const self = this;
204. const nextMessage = self.state.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. isTailMessage(message, index) {
210. const self = this;
211. const nextMessage = self.state.messagesData[index + 1];
212. if (message.isTitle) return false;
213. if (!nextMessage || nextMessage.type !== message.type || nextMessage.name !== message.name) return true;
214. return false;
215. }
216. deleteAttachment(image) {
217. const self = this;
218. const attachments = self.state.attachments;
219. const index = attachments.indexOf(image);
220. attachments.splice(index, 1);
221. self.setState({ attachments });
222. }
223. handleAttachment(e) {
224. const self = this;
225. const attachments = self.state.attachments;
226. const index = self.$$(e.target).parents('label.checkbox').index();
227. const image = self.state.images[index];
228. if (e.target.checked) {
229. // Add to attachments
230. attachments.unshift(image);
231. } else {
232. // Remove from attachments
233. attachments.splice(attachments.indexOf(image), 1);
234. }
235. self.setState({ attachments });
236. }
237. sendMessage() {
238. const self = this;
239. const text = self.messagebar.getValue().replace(/\n/g, '<br>').trim();
240. const messagesToSend = [];
241. self.state.attachments.forEach((attachment) => {
242. messagesToSend.push({
243. image: attachment,
244. });
245. });
246. if (text.trim().length) {
247. messagesToSend.push({
248. text,
249. });
250. }
251. if (messagesToSend.length === 0) {
252. return;
253. }
255. self.setState({
256. // Reset attachments
257. attachments: [],
258. // Hide sheet
259. sheetVisible: false,
260. // Send message
261. messagesData: [...self.state.messagesData, ...messagesToSend],
262. });
263. self.messagebar.clear();
265. // Focus area
266. if (text.length) self.messagebar.focus();
268. // Mock response
269. if (self.state.responseInProgress) return;
270. self.setState({
271. responseInProgress: true,
272. })
273. setTimeout(() => {
274. const answer = self.state.answers[Math.floor(Math.random() * self.state.answers.length)];
275. const person = self.state.people[Math.floor(Math.random() * self.state.people.length)];
276. self.setState({
277. typingMessage: {
278. name: person.name,
279. avatar: person.avatar,
280. },
281. });
282. setTimeout(() => {
283. self.setState({
284. messagesData: [...self.state.messagesData, {
285. text: answer,
286. type: 'received',
287. name: person.name,
288. avatar: person.avatar,
289. }],
290. typingMessage: null,
291. responseInProgress: false,
292. });
293. }, 4000);
294. }, 1000);
295. }
296. };
