Messagebar Vue コンポーネント

    Messagebar Vueコンポーネントは、Framework7のMessagebarコンポーネントを表しています。

    Messagebar コンポーネント

    以下のコンポーネントが含まれています。

    • f7-messagebar - メインのメッセージバー要素
    • f7-messagebar-sheet - メッセージバーのシート要素
    • f7-messagebar-sheet-image - メッセージバーのシートイメージアイテム
    • f7-messagebar-sheet-item - メッセージバーのシートアイテム
    • f7-messagebar-attachments - メッセージバーの添付ファイルの要素
    • f7-messagebar-attachment - 単独のメッセージバー添付ファイル要素

    Messagebar のプロパティ

    PropTypeDefaultDescription
    <f7-messagebar> properties
    initbooleantrueメッセージバーの初期化
    namestringテキストエリアの "name" 属性
    textarea-idstring
    number
    テキストエリアの "id "属性
    placeholderstringMessageテキストエリアのプレースホルダーテキスト
    valuestring
    number
    テキストエリアの値
    readonlybooleanfalsereadonly "テキストエリア属性の設定
    disabledbooleanfalseテキストエリアの "disbled "属性の設定
    send-linkstring送信リンクを有効にし、そのテキストを指定します。このプロパティは、send-linkスロットを使用した場合には無視されます。
    max-heightnumberサイズ変更可能なテキストエリアの最大高さを定義する
    resizablebooleantrueサイズ変更可能なテキストエリアを有効にします。
    sheet-visiblebooleanfalseメッセージバーのシートの表示/非表示を切り替えます。
    attachments-visiblebooleanfalseメッセージバーの添付ファイルの表示/非表示を切り替えます。
    resize-pagebooleantrue有効にすると、メッセージバーのテキストエリアのサイズが変更されたときに、メッセージページのサイズを変更します。
    <f7-messagebar-sheet-image> properties
    imagestringシート画像のURL
    checkedbooleanfalseこのシート画像アイテムがチェックされているかどうかを示します。
    <f7-messagebar-attachment> properties
    imagestring添付ファイル画像のURL
    deletablebooleantrue添付ファイルが削除可能かどうかを指定します。削除可能な場合には、追加の削除ボタンが表示されます。

    メッセージバーのイベント

    EventArgumentsDescription
    <f7-messagebar> events
    change(event)messagebar の textarea 要素で「change」イベントが発生すると、イベントが発生します。
    input(event)イベントは、messagebar textarea要素で「input」イベントが発生すると発生します。
    focus(event)messagebar textarea要素で「focus」イベントが発生するとイベントが発生します。
    blur(event)イベントは、messagebar textarea 要素で「blur」イベントが発生したときにトリガーされます。
    submit
    send
    (value, clear)ユーザがメッセージバーの「送信リンク」をクリックするとイベントが発生する
    <f7-messagebar-sheet-image> events
    change(event)シートアイテムのチェックボックスの変更でイベントが発生する
    <f7-messagebar-attachment> events
    attachment:click(event)添付ファイルをクリックするとイベントが発生する
    attachment:delete(event)添付ファイルの削除ボタンをクリックするとイベントが発生する

    Messagebar Slots

    Messagebar Vue コンポーネントには、カスタムエレメント用の追加スロットがあります。

    • default - 要素は <div class="toolbar-inner"> の最後に挿入されます。
    • buffer-area - 要素はtextareaの直前に挿入されます。メッセージバーの添付ファイルはこちら
    • after-area - 要素はテキストエリアの直後に挿入されます。
    • send-link - 要素は、送信リンクの内側に挿入されます。
    • before-inner - 要素が <div class="toolbar-inner"> の直前に挿入されます。
    • after-inner -
      `.要素の直後に要素が挿入されます。メッセージバーシートはこちら
    • inner-start -
      `. elementの最初に挿入されます。
    • inner-end -
      . elementの最後に挿入されます。default スロットと同じです。
    <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" aurora="f7:arrow_up_fill" md="material:send" slot="send-link"></f7-icon>
      <div>Default slot</div>
    </f7-messagebar>

    レンダリングされます。

    <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>
    

    メッセージバー v-model

    f7-messagebar コンポーネントは value プロップで v-model をサポートしています。

    <template>
      ...
      <f7-messagebar
        v-model:value="messageText"
      />
      ...
    </template>
    <script>
      export default {
        data() {
          messageText: '',
        },
        ...
      };
    </script>
    

    Examples

    ここでは、Messagesと一緒に使えるMessagesページの完全な例を紹介します。

    <template>
    <f7-page>
      <f7-navbar title="Messages" />
    
      <f7-messagebar
        ref="messagebar"
        v-model:value="messageText"
        :placeholder="placeholder"
        :attachments-visible="attachmentsVisible"
        :sheet-visible="sheetVisible"
      >
        <template #inner-start>
          <f7-link
            icon-ios="f7:camera_fill"
            icon-aurora="f7:camera_fill"
            icon-md="material:camera_alt"
            @click="sheetVisible = !sheetVisible"
          />
        </template>
        <template #inner-end>
          <f7-link
            icon-ios="f7:arrow_up_circle_fill"
            icon-aurora="f7:arrow_up_circle_fill"
            icon-md="material:send"
            @click="sendMessage"
          />
        </template>
        <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>
        <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)"
        >
          <template #text>
            <!-- eslint-disable-next-line -->
            <span v-if="message.text" v-html="message.text"></span>
          </template>
        </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>
    import { f7, f7ready } from 'framework7-vue';
    import $ from 'dom7';
    
    export default {
      data() {
        return {
          attachments: [],
          sheetVisible: false,
          typingMessage: null,
          messageText: '',
          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',
            },
          ],
          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',
          ],
          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',
            },
          ],
          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;
        f7ready(() => {
          self.messagebar = f7.messagebar.get(self.$refs.messagebar.$el);
        });
      },
      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 = $(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.messageText.replace(/\n/g, '<br>').trim();
          const messagesToSend = [];
          self.attachments.forEach((attachment) => {
            messagesToSend.push({
              image: attachment,
            });
          });
          if (text.length) {
            messagesToSend.push({
              text,
            });
          }
          if (messagesToSend.length === 0) {
            return;
          }
    
          // Reset attachments
          self.attachments = [];
          // Hide sheet
          self.sheetVisible = false;
          // Clear area
          self.messageText = '';
          // 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>