Messagebar Svelte Component
- Messagebar Components
- Messagebar Properties
- Messagebar Events
- Messagebar Slots
- Access To Messagebar Instance
- Examples
Messagebar Svelte component represents Framework7's Messagebar component.
Messagebar Components
There are following components included:
Messagebar
- main messagebar elementMessagebarSheet
- messagebar sheet elementMessagebarSheetImage
- messagebar sheet image itemMessagebarSheetItem
- messagebar sheet itemMessagebarAttachments
- messagebar attachments elementMessagebarAttachment
- 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 resizable textarea max height | |
resizable | boolean | true | Enables resizable 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 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 Svelte component has additional slots for custom elements:
default
- element will be inserted in the end of<div class="toolbar-inner">
. elementbefore-area
- element will be inserted right before textarea. Messagebar attachments go hereafter-area
- element will be inserted right after textareasend-link
- element will be inserted inside of send linkbefore-inner
- element will be inserted right before<div class="toolbar-inner">
. elementafter-inner
- element will be inserted right after<div class="toolbar-inner">
. element. Messagebar sheet goes hereinner-start
- element will be inserted in the beginning of<div class="toolbar-inner">
. elementinner-end
- element will be inserted in the end of<div class="toolbar-inner">
. element. Same asdefault
slot
<Messagebar placeholder="Message">
<div slot="before-inner">Before inner</div>
<div slot="after-inner">After inner</div>
<div slot="before-area">Before textarea</div>
<div slot="after-area">After textarea</div>
<i class="f7-icons" slot="send-link">arrow_up_fill</i>
<div>Default slot</div>
</Messagebar>
Renders to:
<div class="toolbar messagebar">
<div>Before inner</div>
<div class="toolbar-inner">
<div class="messagebar-area">
<div>Before textarea</div>
<textarea placeholder="Message"></textarea>
<div>After textarea</div>
</div>
<a href="#" class="link">
<i class="f7-icons" slot="send-link">arrow_up_fill</i>
</a>
<div>Default slot</div>
</div>
<div>After inner</div>
</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 calling .instance()
component's method. For example:
<Messagebar bind:this={component}>...</Messagebar>
<script>
let component;
// to get instance in some method
component.instance()
</script>
Examples
Here is how the full example of Messages page where it can be used together with Messages:
<Page>
<Navbar title="Messages" />
<Messagebar
placeholder={placeholder}
attachmentsVisible={attachmentsVisible}
sheetVisible={sheetVisible}
value={messageText}
onInput={(e) => messageText = e.target.value}
>
<a class="link icon-only" slot="inner-start" on:click={() => sheetVisible = !sheetVisible}>
<Icon
ios="f7:camera_fill"
aurora="f7:camera_fill"
md="material:camera_alt"
/>
</a>
<a class="link icon-only" slot="inner-end" on:click={sendMessage}>
<Icon
ios="f7:arrow_up_circle_fill"
aurora="f7:arrow_up_circle_fill"
md="material:send"
/>
</a>
<MessagebarAttachments>
{#each attachments as image, index (index)}
<MessagebarAttachment
key={index}
image={image}
onAttachmentDelete={() => deleteAttachment(image)}
></MessagebarAttachment>
{/each}
</MessagebarAttachments>
<MessagebarSheet>
{#each images as image, index (index)}
<MessagebarSheetImage
key={index}
image={image}
checked={attachments.indexOf(image) >= 0}
onChange={handleAttachment}
></MessagebarSheetImage>
{/each}
</MessagebarSheet>
</Messagebar>
<Messages>
<MessagesTitle><b>Sunday, Feb 9,</b> 12:58</MessagesTitle>
{#each messagesData as message, index (index)}
<Message
type={message.type}
image={message.image}
name={message.name}
avatar={message.avatar}
first={isFirstMessage(message, index)}
last={isLastMessage(message, index)}
tail={isTailMessage(message, index)}
htmlText={message.text}
/>
{/each}
{#if typingMessage}
<Message
type="received"
typing={true}
first={true}
last={true}
tail={true}
header={`${typingMessage.name} is typing`}
avatar={typingMessage.avatar}
></Message>
{/if}
</Messages>
</Page>
<script>
import { onMount } from 'svelte';
import {
f7,
f7ready,
App,
View,
Navbar,
Page,
Messages,
MessagesTitle,
Message,
Messagebar,
Icon,
MessagebarAttachments,
MessagebarAttachment,
MessagebarSheet,
MessagebarSheetImage,
} from 'framework7-svelte';
let messagebarInstance;
let attachments = [];
let sheetVisible = false;
let typingMessage = null;
let messageText = '';
let messagesData = [
{
type: 'sent',
text: 'Hi, Kate',
},
{
type: 'sent',
text: 'How are you?',
},
{
name: 'Kate',
type: 'received',
text: 'Hi, I am good!',
avatar: 'https://cdn.framework7.io/placeholder/people-100x100-9.jpg',
},
{
name: 'Blue Ninja',
type: 'received',
text: 'Hi there, I am also fine, thanks! And how are you?',
avatar: 'https://cdn.framework7.io/placeholder/people-100x100-7.jpg',
},
{
type: 'sent',
text: 'Hey, Blue Ninja! Glad to see you ;)',
},
{
type: 'sent',
text: 'Hey, look, cutest kitten ever!',
},
{
type: 'sent',
image: 'https://cdn.framework7.io/placeholder/cats-200x260-4.jpg',
},
{
name: 'Kate',
type: 'received',
text: 'Nice!',
avatar: 'https://cdn.framework7.io/placeholder/people-100x100-9.jpg',
},
{
name: 'Kate',
type: 'received',
text: 'Like it very much!',
avatar: 'https://cdn.framework7.io/placeholder/people-100x100-9.jpg',
},
{
name: 'Blue Ninja',
type: 'received',
text: 'Awesome!',
avatar: 'https://cdn.framework7.io/placeholder/people-100x100-7.jpg',
},
];
const images = [
'https://cdn.framework7.io/placeholder/cats-300x300-1.jpg',
'https://cdn.framework7.io/placeholder/cats-200x300-2.jpg',
'https://cdn.framework7.io/placeholder/cats-400x300-3.jpg',
'https://cdn.framework7.io/placeholder/cats-300x150-4.jpg',
'https://cdn.framework7.io/placeholder/cats-150x300-5.jpg',
'https://cdn.framework7.io/placeholder/cats-300x300-6.jpg',
'https://cdn.framework7.io/placeholder/cats-300x300-7.jpg',
'https://cdn.framework7.io/placeholder/cats-200x300-8.jpg',
'https://cdn.framework7.io/placeholder/cats-400x300-9.jpg',
'https://cdn.framework7.io/placeholder/cats-300x150-10.jpg',
];
const people = [
{
name: 'Kate Johnson',
avatar: 'https://cdn.framework7.io/placeholder/people-100x100-9.jpg',
},
{
name: 'Blue Ninja',
avatar: 'https://cdn.framework7.io/placeholder/people-100x100-7.jpg',
},
];
const answers = [
'Yes!',
'No',
'Hm...',
'I am not sure',
'And what about you?',
'May be ;)',
'Lorem ipsum dolor sit amet, consectetur',
'What?',
'Are you sure?',
'Of course',
'Need to think about it',
'Amazing!!!',
];
let responseInProgress = false;
$: attachmentsVisible = attachments.length > 0;
$: placeholder = attachments.length > 0 ? 'Add comment or Send' : 'Message';
onMount(() => {
f7ready(() => {
messagebarInstance = f7.messagebar.get('.messagebar');
});
});
function isFirstMessage(message, index) {
const previousMessage = messagesData[index - 1];
if (message.isTitle) return false;
if (
!previousMessage ||
previousMessage.type !== message.type ||
previousMessage.name !== message.name
)
return true;
return false;
}
function isLastMessage(message, index) {
const nextMessage = messagesData[index + 1];
if (message.isTitle) return false;
if (!nextMessage || nextMessage.type !== message.type || nextMessage.name !== message.name)
return true;
return false;
}
function isTailMessage(message, index) {
const nextMessage = messagesData[index + 1];
if (message.isTitle) return false;
if (!nextMessage || nextMessage.type !== message.type || nextMessage.name !== message.name)
return true;
return false;
}
function deleteAttachment(image) {
const index = attachments.indexOf(image);
attachments.splice(index, 1);
attachments = attachments;
}
function handleAttachment(e) {
const index = f7.$(e.target).parents('label.checkbox').index();
const image = images[index];
if (e.target.checked) {
// Add to attachments
attachments.unshift(image);
} else {
// Remove from attachments
attachments.splice(attachments.indexOf(image), 1);
}
attachments = attachments;
}
function sendMessage() {
const text = messageText.replace(/\n/g, '<br>').trim();
const messagesToSend = [];
attachments.forEach((attachment) => {
messagesToSend.push({
type: 'sent',
image: attachment,
});
});
if (text.length) {
messagesToSend.push({
text,
type: 'sent',
});
}
if (messagesToSend.length === 0) {
return;
}
// Reset attachments
attachments = [];
// Hide sheet
sheetVisible = false;
// Send message
messagesData = [...messagesData, ...messagesToSend];
// Clear
messageText = '';
messagebarInstance.clear();
// Focus area
if (text.length) messagebarInstance.focus();
// Mock response
if (responseInProgress) return;
responseInProgress = true;
setTimeout(() => {
const answer = answers[Math.floor(Math.random() * answers.length)];
const person = people[Math.floor(Math.random() * people.length)];
typingMessage = {
name: person.name,
avatar: person.avatar,
};
setTimeout(() => {
messagesData = [
...messagesData,
{
text: answer,
type: 'received',
name: person.name,
avatar: person.avatar,
},
];
typingMessage = null;
responseInProgress = false;
}, 4000);
}, 1000);
}
</script>