Messagebar Vue Component

    Messagebar Vue component represents Framework7's Messagebar component.

    Messagebar Components

    There are following components included:

    • f7-messagebar - main messagebar element
    • f7-messagebar-sheet - messagebar sheet element
    • f7-messagebar-sheet-image - messagebar sheet image item
    • f7-messagebar-sheet-item - messagebar sheet item
    • f7-messagebar-attachments - messagebar attachments element
    • f7-messagebar-attachment - single messagebar attachment element

    Messagebar Properties

    Prop Type Default Description
    <f7-messagebar> properties
    init boolean true Initializes Messagebar
    name string Textarea "name" attribute
    textarea-id 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
    send-link string Enables Send link and specifies its text. This property will be ignored in case you use send-link slot
    max-height number Defines resizeable textarea max height
    resizable bolean true Enables resizeable textarea
    sheet-visible boolean false Makes messagebar sheet visible/active
    attachments-visible boolean false Makes messagebar attachments visible/active
    resize-page boolean true When enabled, it will resize messages page when messagebar textarea size changed
    <f7-messagebar-sheet-image> properties
    image string Sheet image URL
    checked boolean false Indicates whether this sheet image-item is checked or not
    <f7-messagebar-attachment> 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

    <f7-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
    <f7-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"
    <f7-messagebar-sheet-image> events
    change (event) Event will be triggered on sheet item checkbox change
    <f7-messagebar-attachment> events
    attachment:click (event) Event will be triggered on attachment click
    attachment:delete (event) Event will be triggered on attachment delete button click

    Messagebar Slots

    Messagebar Vue 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 as default slot
    <f7-messagebar placeholder="Message" @submit="onSubmit">
      <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>
      <f7-icon ios="f7:arrow_up_fill" md="material:send" slot="send-link"></f7-icon>
      <div>Default slot</div>
    </f7-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="icon f7-icons">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 accessing .f7Messagebar component's property.

    Examples

    Here is how the full example of Messages page where it can be used together with Messages:

    <template>
      <f7-page>
        <f7-navbar title="Messsages"></f7-navbar>
    
        <f7-messagebar
          :placeholder="placeholder"
          ref="messagebar"
          :attachments-visible="attachmentsVisible"
          :sheet-visible="sheetVisible"
        >
          <f7-link
            icon-ios="f7:camera_fill"
            icon-md="material:camera_alt"
            slot="inner-start"
            @click="sheetVisible = !sheetVisible"
          ></f7-link>
          <f7-link
            icon-ios="f7:arrow_up_fill"
            icon-md="material:send"
            slot="inner-end"
            @click="sendMessage"
          ></f7-link>
          <f7-messagebar-attachments>
            <f7-messagebar-attachment
              v-for="(image, index) in attachments"
              :key="index"
              :image="image"
              @attachment:delete="deleteAttachment(image)"
            ></f7-messagebar-attachment>
          </f7-messagebar-attachments>
          <f7-messagebar-sheet>
            <f7-messagebar-sheet-image
              v-for="(image, index) in images"
              :key="index"
              :image="image"
              :checked="attachments.indexOf(image) >= 0"
              @change="handleAttachment"
            ></f7-messagebar-sheet-image>
          </f7-messagebar-sheet>
        </f7-messagebar>
    
        <f7-messages ref="messages">
          <f7-messages-title><b>Sunday, Feb 9,</b> 12:58</f7-messages-title>
          <f7-message
            v-for="(message, index) in messagesData"
            :key="index"
            :type="message.type"
            :image="message.image"
            :name="message.name"
            :avatar="message.avatar"
            :first="isFirstMessage(message, index)"
            :last="isLastMessage(message, index)"
            :tail="isTailMessage(message, index)"
          >
            <span slot="text" v-if="message.text" v-html="message.text"></span>
          </f7-message>
          <f7-message v-if="typingMessage"
            type="received"
            :typing="true"
            :first="true"
            :last="true"
            :tail="true"
            :header="`${typingMessage.name} is typing`"
            :avatar="typingMessage.avatar"
          ></f7-message>
        </f7-messages>
      </f7-page>
    </template>
    <script>
      export default {
        data() {
          return {
            attachments: [],
            sheetVisible: false,
            typingMessage: null,
            messagesData: [
              {
                type: 'sent',
                text: 'Hi, Kate',
              },
              {
                type: 'sent',
                text: 'How are you?',
              },
              {
                name: 'Kate',
                type: 'received',
                text: 'Hi, I am good!',
                avatar: 'http://lorempixel.com/100/100/people/9',
              },
              {
                name: 'Blue Ninja',
                type: 'received',
                text: 'Hi there, I am also fine, thanks! And how are you?',
                avatar: 'http://lorempixel.com/100/100/people/7',
              },
              {
                type: 'sent',
                text: 'Hey, Blue Ninja! Glad to see you ;)',
              },
              {
                type: 'sent',
                text: 'Hey, look, cutest kitten ever!',
              },
              {
                type: 'sent',
                image: 'http://lorempixel.com/200/260/cats/4/',
    
              },
              {
                name: 'Kate',
                type: 'received',
                text: 'Nice!',
                avatar: 'http://lorempixel.com/100/100/people/9',
              },
              {
                name: 'Kate',
                type: 'received',
                text: 'Like it very much!',
                avatar: 'http://lorempixel.com/100/100/people/9',
              },
              {
                name: 'Blue Ninja',
                type: 'received',
                text: 'Awesome!',
                avatar: 'http://lorempixel.com/100/100/people/7',
              },
            ],
            images: [
              'http://lorempixel.com/300/300/cats/1/',
              'http://lorempixel.com/200/300/cats/2/',
              'http://lorempixel.com/400/300/cats/3/',
              'http://lorempixel.com/300/150/cats/4/',
              'http://lorempixel.com/150/300/cats/5/',
              'http://lorempixel.com/300/300/cats/6/',
              'http://lorempixel.com/300/300/cats/7/',
              'http://lorempixel.com/200/300/cats/8/',
              'http://lorempixel.com/400/300/cats/9/',
              'http://lorempixel.com/300/150/cats/10/',
            ],
            people: [
              {
                name: 'Kate Johnson',
                avatar: 'http://lorempixel.com/100/100/people/9',
              },
              {
                name: 'Blue Ninja',
                avatar: 'http://lorempixel.com/100/100/people/7',
              },
            ],
            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!!!',
            ],
            responseInProgress: false,
          };
        },
        computed: {
          attachmentsVisible() {
            const self = this;
            return self.attachments.length > 0;
          },
          placeholder() {
            const self = this;
            return self.attachments.length > 0 ? 'Add comment or Send' : 'Message';
          },
        },
        mounted() {
          const self = this;
          self.$f7ready(() => {
            self.messagebar = self.$refs.messagebar.f7Messagebar;
            self.messages = self.$refs.messages.f7Messages;
          });
        },
        methods: {
          isFirstMessage(message, index) {
            const self = this;
            const previousMessage = self.messagesData[index - 1];
            if (message.isTitle) return false;
            if (!previousMessage || previousMessage.type !== message.type || previousMessage.name !== message.name) return true;
            return false;
          },
          isLastMessage(message, index) {
            const self = this;
            const nextMessage = self.messagesData[index + 1];
            if (message.isTitle) return false;
            if (!nextMessage || nextMessage.type !== message.type || nextMessage.name !== message.name) return true;
            return false;
          },
          isTailMessage(message, index) {
            const self = this;
            const nextMessage = self.messagesData[index + 1];
            if (message.isTitle) return false;
            if (!nextMessage || nextMessage.type !== message.type || nextMessage.name !== message.name) return true;
            return false;
          },
          deleteAttachment(image) {
            const self = this;
            const index = self.attachments.indexOf(image);
            self.attachments.splice(index, 1)[0]; // eslint-disable-line
          },
          handleAttachment(e) {
            const self = this;
            const index = self.$$(e.target).parents('label.checkbox').index();
            const image = self.images[index];
            if (e.target.checked) {
              // Add to attachments
              self.attachments.unshift(image);
            } else {
              // Remove from attachments
              self.attachments.splice(self.attachments.indexOf(image), 1);
            }
          },
          sendMessage() {
            const self = this;
            const text = self.messagebar.getValue().replace(/\n/g, '<br>').trim();
            const messagesToSend = [];
            self.attachments.forEach((attachment) => {
              messagesToSend.push({
                image: attachment,
              });
            });
            if (text.trim().length) {
              messagesToSend.push({
                text,
              });
            }
            if (messagesToSend.length === 0) {
              return;
            }
    
            // Reset attachments
            self.attachments = [];
            // Hide sheet
            self.sheetVisible = false;
            // Clear area
            self.messagebar.clear();
            // Focus area
            if (text.length) self.messagebar.focus();
            // Send message
            self.messagesData.push(...messagesToSend);
    
            // Mock response
            if (self.responseInProgress) return;
            self.responseInProgress = true;
            setTimeout(() => {
              const answer = self.answers[Math.floor(Math.random() * self.answers.length)];
              const person = self.people[Math.floor(Math.random() * self.people.length)];
              self.typingMessage = {
                name: person.name,
                avatar: person.avatar,
              };
              setTimeout(() => {
                self.messagesData.push({
                  text: answer,
                  type: 'received',
                  name: person.name,
                  avatar: person.avatar,
                });
                self.typingMessage = null;
                self.responseInProgress = false;
              }, 4000);
            }, 1000);
          },
        },
      };
    </script>