メッセージコンポーネント

    Messages Svelteコンポーネントは、Messagesコンポーネントを表しています。

    メッセージコンポーネント

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

    • Messages - メインのメッセージコンテナ
    • Message - 単一のメッセージ要素
    • MessagesTitle - ひとつのメッセージのタイトル要素

    メッセージのプロパティ

    PropTypeDefaultDescription
    <Messages> properties
    initbooleantrueInitializes Messages component
    newMessagesFirstbooleanfalseEnable if you want to use new messages on top, instead of having them on bottom
    scrollMessagesbooleantrueEnable/disable messages autoscrolling when adding new message
    scrollMessagesOnEdgebooleantrueIf enabled then messages autoscrolling will happen only when user is on top/bottom of the messages view
    typingbooleanfalseAllows to display/toggle typing message indicator
    <Message> properties
    typestringsentMessage type: sent (default) or received
    textstringMessage text
    avatarstringMessage user's avatar URL
    namestringMessage user's name
    imagestringMessage image URL
    headerstringMessage header
    footerstringMessage footer
    textHeaderstringMessage text header
    textFooterstringMessage text footer
    firstbooleanfalseDefines that the message is first in the conversation
    lastbooleanfalseDefines that the message is last in the conversation
    tailbooleanfalseDefines that the message has visual "tail". Usually last message in conversation
    sameNamebooleanfalseDefines that this message sender name is the same as on previous message
    sameHeaderbooleanfalseDefines that this message header text is the same as on previous message
    sameFooterbooleanfalseDefines that this message footer text is the same as on previous message
    sameAvatarbooleanfalseDefines that this message user's avatar URL is the same as on previous message

    メッセージイベント

    EventDescription
    <Message> events
    clickユーザーがメッセージのバブルをクリックするとイベントが発生する
    clickNameユーザーがメッセージのユーザー名をクリックするとイベントが発生する
    clickTextユーザがメッセージのテキストをクリックするとイベントが発生する
    clickAvatarユーザがメッセージユーザのアバターをクリックするとイベントが発生する
    clickHeaderユーザがメッセージのヘッダをクリックするとイベントが発生する
    clickFooterユーザーがメッセージのフッターをクリックするとイベントが発生する
    clickBubbleユーザがメッセージバブルをクリックするとイベントが発生します。

    メッセージスロット

    シングルメッセージのSvelteコンポーネント(<Message>)には、カスタムエレメント用のスロットが追加されています。

    • default - 要素は、最後に <div class="message-bubble"> 要素の子として挿入されます。
    • start - 要素は先頭に挿入され、メインのメッセージ要素 <div class="message"> の直接の子となります。
    • end - メインのメッセージ要素の直系の子として、最後に要素が挿入されます。
    • content-start - 要素は <div class="message-content"> 要素の先頭に挿入され、その直接の子となります。
    • content-end - <div class="message-content"> 要素の最後に挿入され、直接の子要素となります。
    • bubble-start -
      ` 要素の先頭に挿入され、直接の子要素となります。
    • bubble-end - <div class="message-bubble"> 要素の最後に挿入され、直接の子となります。default` スロットと同じです。

    以下のスロットは、1つのメッセージの中で、同じプロップの代わりに、より完全なレイアウトを渡す必要がある場合に使用できます。

    • header - 要素はメッセージのヘッダーに挿入されます。
    • footer - メッセージのフッターに挿入される要素です。
    • text - メッセージのテキストに挿入される要素です。
    • name - メッセージの名前に挿入される要素です。
    • image - メッセージのイメージに挿入される要素です(<img> 要素になります)。
    • text-header - メッセージのテキストヘッダーに挿入される要素です。
    • text-footer - メッセージのテキストフッターに挿入される要素です。
    <Message
      type="sent"
      text="Hello World"
      name="John Doe"
      avatar="path/to/image.jpg"
    >
      <div slot="start">Start</div>
      <div slot="end">End</div>
      <div slot="content-start">Content Start</div>
      <div slot="content-end">Content End</div>
      <div slot="bubble-start">Bubble Start</div>
      <div slot="bubble-end">Bubble End</div>
    </Message>
    
    <!-- にレンダリングされます。 -->
    
    <div class="message message-sent">
      <div>Start</div>
      <div class="message-avatar" style="background-image: url(path/to/image.jpg);"></div>
      <div class="message-content">
        <div>Content Start</div>
        <div class="message-name">John Doe</div>
        <div class="message-bubble">
          <div>Bubble Start</div>
          <div class="message-text">Hello World</div>
          <div>Bubble End</div>
        </div>
        <div>Content End</div>
      </div>
      <div>End</div>
    </div>
    

    メッセージへのアクセス インスタンス

    自動改行機能を使ってメッセージを初期化し(init={true}というプロパティーを使って)、メッセージAPIを使う必要がある場合、.instance()コンポーネントのメソッドを呼び出すことで、初期化されたインスタンスにアクセスすることができます。例えば

    <Messages bind:this={component}>...</Messages>
    
    <script>
      let component;
    
      // あるメソッドでインスタンスを取得する
      component.instance()
    </script>
    
    

    Examples

    ここでは、Messagebarと一緒に使用できる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>