Message Attachments

The Chat messages may contain attachments such as images, videos, or data.

Supported Attachment Types

The Chat provides built-in support for displaying:

  • Images—The contentType has to start with "image/". The content has to be a valid URL.
  • Plain-text attachments—The built-in Chat template displays any content other than images as text.

Defining Attachments

To define attachments for a message:

  1. Populate the attachments field of the message.
  2. Set the content and an optional contentType for each Attachment. Typically, the content type identifier for the attachment is MIME, but you can also use a string.

Display Modes

By default, message attachments are displayed as a carousel or card deck below the message. You can also display attachments in a list by setting the attachmentLayout of the message.

import React from 'react';
import ReactDOM from 'react-dom';
import { Chat } from '@progress/kendo-react-conversational-ui';

class App extends React.Component {
    constructor(props) {
        super(props);
        this.user = {
            id: 1,
            name: "John"
        };
        this.bot = {
            id: 0
        };
        this.attachments = [ {
            content: 'The Westin Copley Place, Boston',
            contentType: 'hotel'
        }, {
            content: 'Boston Park Plaza',
            contentType: 'hotel'
        }, {
            content: 'Sheraton Boston Hotel',
            contentType: 'hotel'
        }, {
            content: 'InterContinental Boston',
            contentType: 'hotel'
        } ];
        this.state = {
            messages: [ {
                author: this.bot,
                text: 'A message with attachments carousel',
                attachments: this.attachments
            }, {
                author: this.bot,
                text: 'A message with attachments list',
                attachmentLayout: 'list',
                attachments: this.attachments
            } ]
        };
    }

    render() {
        return (
            <div>
                <Chat user={this.user}
                    messages={this.state.messages}
                    width={400}>
                </Chat>
            </div>
        );
    }
}

ReactDOM.render(
    <App />,
    document.querySelector('my-app')
);

Attachment Templates

To customize the attachments, define an AttachmentTemplate. To get the default appearance of the built-in attachment template, wrap the template content in a "k-card" container.

import React from 'react';
import ReactDOM from 'react-dom';
import { conversation, user } from './conversation.jsx';
import { Chat } from '@progress/kendo-react-conversational-ui';

function AttachmentTemplate(props) {
    let attachment = props.item;
    if (attachment.contentType === 'hotel') {
        return <a href={attachment.site} target="_blank" draggable={false} tabIndex={-1}>
            <img style={{ width: 150 }}src={attachment.thumb} draggable={false} />
        </a>;
    } else if (attachment.contentType.match('^image/')) {
        return <img src={attachment.content} draggable={false} />;
    } else if (attachment.contentType === 'text/plain') {
        return attachment.content;
    } else {
        return null;
    }
}

class App extends React.Component {
    constructor(props) {
        super(props);
        this.user = user;
        this.state = {
            messages: conversation
        };
    }

    addNewMessage = (event) => {
        this.setState((prevState) => {
            return { messages: [ ...prevState.messages, event.message ] };
        });
    };

    render() {
        return (
            <div>
                <Chat user={this.user}
                    messages={this.state.messages}
                    onMessageSend={this.addNewMessage}
                    width={400}
                    attachmentTemplate={AttachmentTemplate}>
                </Chat>
            </div>
        );
    }
}

ReactDOM.render(
    <App />,
    document.querySelector('my-app')
);
export const bot = {
    id: 0,
    name: 'Travel Agent',
    avatarUrl: "https://via.placeholder.com/24/800080/800080.png"
};

export const user = {
    id: 1,
    avatarUrl: "https://via.placeholder.com/24/008000/008000.png"
};

export const conversation = [ {
    author: bot,
    text: 'Hello, what kind of trip would you like to book?',
    suggestedActions: [ {
        type: 'reply',
        value: 'Business trip'
    }, {
        type: 'reply',
        value: 'Leisure trip'
    } ],
    timestamp: new Date('2018-02-27 21:00')
}, {
    author: user,
    text: 'Business trip',
    timestamp: new Date('2018-02-27 21:01')
}, {
    author: bot,
    text: `What destinations would you like to visit?`,
    timestamp: new Date('2018-02-27 21:01')
}, {
    author: user,
    text: `Exotic`,
    timestamp: new Date('2018-02-28 00:05')
}, {
    author: bot,
    text: `And the date you need to be there?`,
    timestamp: new Date('2018-02-28 00:05')
}, {
    author: user,
    text: `april 1`,
    timestamp: new Date('2018-02-28 00:15')
}, {
    author: bot,
    text: `What is the duration of your stay?`,
    suggestedActions: [ {
        type: 'reply',
        value: '1 week'
    }, {
        type: 'reply',
        value: '2 weeks'
    }, {
        type: 'reply',
        value: '1 month'
    } ],
    timestamp: new Date('2018-02-28 00:15')
}, {
    author: user,
    text: `3 days`,
    timestamp: new Date('2018-02-28 00:20')
}, {
    author: bot,
    text: `I've picked these hotels for you`,
    attachments: [ {
        title: 'Mystique',
        contentType: 'hotel',
        thumb: 'https://demos.telerik.com/kendo-ui/content/chat/Mystique.png',
        site: 'http://mystique.gr/'
    }, {
        title: 'Rimondi',
        contentType: 'hotel',
        thumb: 'https://demos.telerik.com/kendo-ui/content/chat/Rimondi.png',
        site: 'http://www.hotelsrimondi.com/'
    }, {
        title: 'Amanzoe',
        contentType: 'hotel',
        thumb: 'https://demos.telerik.com/kendo-ui/content/chat/Amanzoe.png',
        site: 'https://www.aman.com/resorts/amanzoe'
    } ],
    attachmentLayout: 'carousel',
    timestamp: new Date('2018-02-28 00:15')
}, {
    author: user,
    text: `Mystique`,
    timestamp: new Date('2018-02-28 00:20')
}, {
    author: bot,
    text: `Is this correct?`,
    suggestedActions: [ {
        type: 'reply',
        value: 'Yes'
    }, {
        type: 'reply',
        value: 'No'
    } ],
    attachments: [ {
        contentType: 'text/plain',
        content: 'Arrival date: April 1, 2018; Departure date: April 3, 2018; Staying at Mystique.'
    } ],
    timestamp: new Date('2018-02-28 00:35')
}, {
    author: user,
    text: `yeah`,
    timestamp: new Date('2018-02-28 00:40')
}, {
    author: bot,
    text: `Great. Your reservation number is #1234`,
    suggestedActions: [ {
        type: 'reply',
        value: 'Book another trip'
    }, {
        type: 'reply',
        value: 'Make changes to the current trip'
    }, {
        type: 'reply',
        value: 'Make changes to a different trip'
    } ],
    timestamp: new Date('2018-02-28 00:41')
} ];

In this article