Templates in EJ2 TypeScript Chat UI control

17 Dec 202424 minutes to read

The Chat UI control provides several templates for customizing the appearance of the empty conversation area, messages, typing indicator, and more. These templates provide flexibility for users to create a unique, personalized chat experience.

Empty chat template

You can use the emptyChatTemplate property to customize the chat interface when no messages are displayed. Personalized content, such as welcome messages or images, can be added to create an engaging and inviting experience for users starting a conversation.

import { ChatUI } from '@syncfusion/ej2-interactive-chat';
import { enableRipple } from '@syncfusion/ej2-base';

enableRipple(true);

// Initializes the Chat UI control
let chatUI: ChatUI = new ChatUI({
    emptyChatTemplate: '<div class="empty-chat-text"><h4><span class="e-icons e-comment-show"></span></h4><h4>No Messages Yet</h4><p>Start a conversation to see your messages here.</p></div>',
});

// Render initialized Chat UI.
chatUI.appendTo('#emptyChatTemplate');
<!DOCTYPE html>
<html lang="en">

<head>
    <title>EJ2 Chat UI</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="TypeScript Chat UI Control" />
    <meta name="author" content="Syncfusion" />
    <link href="index.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/30.1.37/ej2-base/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/30.1.37/ej2-inputs/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/30.1.37/ej2-buttons/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/30.1.37/ej2-navigations/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/30.1.37/ej2-popups/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/30.1.37/ej2-interactive-chat/styles/material.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
    <script src="systemjs.config.js"></script>
    <style>
        .empty-chat-text {
            font-size: 15px;
            text-align: center;
            margin-top: 90px;
        }
    </style>
<script src="https://cdn.syncfusion.com/ej2/syncfusion-helper.js" type ="text/javascript"></script>
</head>
<body>
    <div id='loader'>Loading....</div>
    <div id='container' style="height: 380px; width: 450px;">
        <div id="emptyChatTemplate"></div>
    </div>
</body>
</html>
#container {
    visibility: hidden;
    margin: 20px auto;
}

#loader {
    color: #008cff;
    height: 40px;
    left: 45%;
    position: absolute;
    top: 45%;
    width: 30%;
}

Message template

You can use the messageTemplate property to customize the appearance and styling of each chat message. Modify text styling, layout, and other design elements to ensure a personalized chat experience. The template context includes message and index items.

import { ChatUI, UserModel, MessageModel } from '@syncfusion/ej2-interactive-chat';
import { enableRipple } from '@syncfusion/ej2-base';

enableRipple(true);

let currentUserModel: UserModel = {
    id: "user1",
    user: "Albert"
};

let michaleUserModel: UserModel = {
    id: "user2",
    user: "Michale Suyama"
};
let chatMessages: MessageModel[] = [
    {
        author: currentUserModel,
        text: "Hi Michale, are we on track for the deadline?"
    },
    {
        author: michaleUserModel,
        text: "Yes, the design phase is complete."
    },
    {
        author: currentUserModel,
        text: "I’ll review it and send feedback by today."
    }
];
// Initializes the Chat UI control
let chatUI: ChatUI = new ChatUI({
    messages: chatMessages,
    user: currentUserModel,
    messageTemplate: (context: any) => messageTemplate(context)
});

// Render initialized Chat UI.
chatUI.appendTo('#messageTemplate');

function messageTemplate(context: any): string {
    return ` <div class="message-items e-card">
                <div class="message-text">${context.message.text}</div>
            </div>`;
}
<!DOCTYPE html>
<html lang="en">

<head>
    <title>EJ2 Chat UI</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="TypeScript Chat UI Control" />
    <meta name="author" content="Syncfusion" />
    <link href="index.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/30.1.37/ej2-base/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/30.1.37/ej2-inputs/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/30.1.37/ej2-buttons/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/30.1.37/ej2-navigations/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/30.1.37/ej2-popups/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/30.1.37/ej2-interactive-chat/styles/material.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
    <script src="systemjs.config.js"></script>
    <style>
        #messageTemplate .e-right .message-items {
            border-radius: 16px 16px 2px 16px;
            background-color: #c5ffbf;
        }

        #messageTemplate .e-left .message-items {
            border-radius: 16px 16px 16px 2px;
            background-color: #f5f5f5;
        }

        #messageTemplate .message-items {
            padding: 5px;
        }
    </style>
<script src="https://cdn.syncfusion.com/ej2/syncfusion-helper.js" type ="text/javascript"></script>
</head>
<body>
    <div id='loader'>Loading....</div>
    <div id='container' style="height: 380px; width: 450px;">
        <div id="messageTemplate"></div>
    </div>
</body>
</html>
#container {
    visibility: hidden;
    margin: 20px auto;
}

#loader {
    color: #008cff;
    height: 40px;
    left: 45%;
    position: absolute;
    top: 45%;
    width: 30%;
}

Time break template

You can use the timeBreakTemplate property to customize the template, such as showing “Today,” “Yesterday,” or specific dates. This enhances conversation organization by clearly separating messages based on time, improving readability for the user. The template context includes messageDate.

import { ChatUI, UserModel, MessageModel } from '@syncfusion/ej2-interactive-chat';
import { enableRipple } from '@syncfusion/ej2-base';

enableRipple(true);

let currentUserModel: UserModel = {
    id: "user1",
    user: "Albert"
};

let michaleUserModel: UserModel = {
    id: "user2",
    user: "Michale Suyama"
};
let chatMessages: MessageModel[] = [
    {
        author: currentUserModel,
        text: "Hi Michale, are we on track for the deadline?",
        timeStamp: new Date("December 25, 2024 7:30")
    },
    {
        author: michaleUserModel,
        text: "Yes, the design phase is complete.",
        timeStamp: new Date("December 25, 2024 8:00")
    },
    {
        author: currentUserModel,
        text: "I’ll review it and send feedback by today.",
        timeStamp: new Date("December 25, 2024 11:00")
    }
];
// Initializes the Chat UI control
let chatUI: ChatUI = new ChatUI({
    messages: chatMessages,
    user: currentUserModel,
    showTimeBreak: true,
    timeBreakTemplate: timeBreakTemplate
});

// Render initialized Chat UI.
chatUI.appendTo('#timeBreakTemplate');

function timeBreakTemplate(context: any): string {
    const date: Date = new Date(context.messageDate);
    const day: string = String(date.getDate()).padStart(2, '0');
    const month: string = String(date.getMonth() + 1).padStart(2, '0');
    const year: number = date.getFullYear();
    let hours: number = date.getHours();
    const minutes: string = String(date.getMinutes()).padStart(2, '0');
    const ampm: string = hours >= 12 ? 'PM' : 'AM';
    hours = hours % 12 || 12;
    const formattedDate: string = `${day}/${month}/${year} ${hours}:${minutes} ${ampm}`;
    return `<div class="timebreak-wrapper">${formattedDate}</div>`;
}
<!DOCTYPE html>
<html lang="en">

<head>
    <title>EJ2 Chat UI</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="TypeScript Chat UI Control" />
    <meta name="author" content="Syncfusion" />
    <link href="index.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/30.1.37/ej2-base/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/30.1.37/ej2-inputs/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/30.1.37/ej2-buttons/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/30.1.37/ej2-navigations/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/30.1.37/ej2-popups/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/30.1.37/ej2-interactive-chat/styles/material.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
    <script src="systemjs.config.js"></script>
    <style>
        #timeBreakTemplate .timebreak-wrapper {
            background-color: #6495ed;
            color: #ffffff;
            border-radius: 5px;
            padding: 2px;
        }
    </style>
<script src="https://cdn.syncfusion.com/ej2/syncfusion-helper.js" type ="text/javascript"></script>
</head>
<body>
    <div id='loader'>Loading....</div>
    <div id='container' style="height: 380px; width: 450px;">
        <div id="timeBreakTemplate"></div>
    </div>
</body>
</html>
#container {
    visibility: hidden;
    margin: 20px auto;
}

#loader {
    color: #008cff;
    height: 40px;
    left: 45%;
    position: absolute;
    top: 45%;
    width: 30%;
}

Typing indicator template

You can use the typingUsersTemplate property to customize the display of users currently typing in the chat. It allows for styling and positioning of the typing indicator, enhancing the user experience. The template context includes Users.

import { ChatUI, UserModel, MessageModel } from '@syncfusion/ej2-interactive-chat';
import { enableRipple } from '@syncfusion/ej2-base';

enableRipple(true);

let currentUserModel: UserModel = {
    id: "user1",
    user: "Albert"
};

let michaleUserModel: UserModel = {
    id: "user2",
    user: "Michale Suyama"
};
let reenaUserModel: UserModel = {
    id: "user3",
    user: "Reena"
};
let typingUsers : UserModel[] = [michaleUserModel, reenaUserModel];
let chatMessages: MessageModel[] = [
    {
        author: currentUserModel,
        text: "Hi Michale, are we on track for the deadline?"
    },
    {
        author: michaleUserModel,
        text: "Yes, the design phase is complete."
    },
    {
        author: currentUserModel,
        text: "I’ll review it and send feedback by today."
    }
];
// Initializes the Chat UI control
let chatUI: ChatUI = new ChatUI({
    messages: chatMessages,
    user: currentUserModel,
    typingUsers: typingUsers,
    typingUsersTemplate: typingUsersTemplate
});

// Render initialized Chat UI.
chatUI.appendTo('#typingUsersTemplate');

function typingUsersTemplate(context: any): string {
    if (!context.users || context.users.length === 0) {
        return '';
    }

    const usersList = context.users.map((user: any, i: number) => {
        const isLastUser: boolean = i === context.users.length - 1;
        return `${isLastUser && i > 0 ? 'and ' : ''}<span class="typing-user">${user.user}</span>`;
    }).join(' ');

    return `
        <div class="typing-wrapper">
            ${usersList} are typing...
        </div>
    `;
}
<!DOCTYPE html>
<html lang="en">

<head>
    <title>EJ2 Chat UI</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="TypeScript Chat UI Control" />
    <meta name="author" content="Syncfusion" />
    <link href="index.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/30.1.37/ej2-base/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/30.1.37/ej2-inputs/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/30.1.37/ej2-buttons/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/30.1.37/ej2-navigations/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/30.1.37/ej2-popups/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/30.1.37/ej2-interactive-chat/styles/material.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
    <script src="systemjs.config.js"></script>
    <style>
        #typingUsersTemplate .typing-wrapper {
            display: flex;
            gap: 4px;
            align-items: center;
            font-family: Arial, sans-serif;
            font-size: 14px;
            color: #555;
            margin: 5px 0;
        }
        .typing-user {
            font-weight: bold;
            color: #0078d4;
        }
    </style>
<script src="https://cdn.syncfusion.com/ej2/syncfusion-helper.js" type ="text/javascript"></script>
</head>
<body>
    <div id='loader'>Loading....</div>
    <div id='container' style="height: 380px; width: 450px;">
        <div id="typingUsersTemplate"></div>
    </div>
</body>
</html>
#container {
    visibility: hidden;
    margin: 20px auto;
}

#loader {
    color: #008cff;
    height: 40px;
    left: 45%;
    position: absolute;
    top: 45%;
    width: 30%;
}

Suggestion template

You can use the suggestionTemplate property to customize the quick reply suggestions that appear above the input field. Templates here can help create visually appealing and functional suggestion layouts. The template context includes suggestion and index items.

import { ChatUI, UserModel, MessageModel } from '@syncfusion/ej2-interactive-chat';
import { enableRipple } from '@syncfusion/ej2-base';

enableRipple(true);

let currentUserModel: UserModel = {
    id: "user1",
    user: "Albert"
};

let michaleUserModel: UserModel = {
    id: "user2",
    user: "Michale Suyama"
};
let suggestions : string[] = [ "Okay will check it", "Sounds good!"];
let chatMessages: MessageModel[] = [
    {
        author: currentUserModel,
        text: "Hi Michale, are we on track for the deadline?"
    },
    {
        author: michaleUserModel,
        text: "Yes, the design phase is complete."
    }
];
// Initializes the Chat UI control
let chatUI: ChatUI = new ChatUI({
    messages: chatMessages,
    user: currentUserModel,
    suggestions: suggestions,
    suggestionTemplate: suggestionTemplate
});

// Render initialized Chat UI.
chatUI.appendTo('#suggestionTemplate');

function suggestionTemplate(context: any): string {
    return `
        <div class='suggestion-item active'>
            <div class="content">${context.suggestion}</div>
        </div>
    `;
}
<!DOCTYPE html>
<html lang="en">

<head>
    <title>EJ2 Chat UI</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="TypeScript Chat UI Control" />
    <meta name="author" content="Syncfusion" />
    <link href="index.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/30.1.37/ej2-base/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/30.1.37/ej2-inputs/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/30.1.37/ej2-buttons/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/30.1.37/ej2-navigations/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/30.1.37/ej2-popups/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/30.1.37/ej2-interactive-chat/styles/material.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
    <script src="systemjs.config.js"></script>
    <style>
        #suggestionTemplate .e-suggestion-list li {
            padding: 0;
            border: none;
            box-shadow: none;
        }
        #suggestionTemplate .suggestion-item {
            display: flex;
            align-items: center;
            background-color: #87b6fb;
            color: black;
            padding: 4px;
            gap: 5px;
            height: 30px;
            border-radius: 5px;
        }
        #suggestionTemplate .suggestion-item .content {
            padding: 0;
            text-overflow: ellipsis;
            white-space: nowrap;
            overflow: hidden;
        }
    </style>
<script src="https://cdn.syncfusion.com/ej2/syncfusion-helper.js" type ="text/javascript"></script>
</head>
<body>
    <div id='loader'>Loading....</div>
    <div id='container' style="height: 380px; width: 450px;">
        <div id="suggestionTemplate"></div>
    </div>
</body>
</html>
#container {
    visibility: hidden;
    margin: 20px auto;
}

#loader {
    color: #008cff;
    height: 40px;
    left: 45%;
    position: absolute;
    top: 45%;
    width: 30%;
}

You can use the footerTemplate property to customize the default footer area and manage message send actions with a personalized design. This flexibility allows users to create unique footers that meet their specific needs.

import { ChatUI, UserModel, MessageModel } from '@syncfusion/ej2-interactive-chat';
import { enableRipple } from '@syncfusion/ej2-base';

enableRipple(true);

let currentUserModel: UserModel = {
    id: "user1",
    user: "Albert"
};

let michaleUserModel: UserModel = {
    id: "user2",
    user: "Michale Suyama"
};
let chatMessages: MessageModel[] = [
    {
        author: currentUserModel,
        text: "Hi Michale, are we on track for the deadline?"
    },
    {
        author: michaleUserModel,
        text: "Yes, the design phase is complete."
    },
    {
        author: currentUserModel,
        text: "I’ll review it and send feedback by today."
    }
];
// Initializes the Chat UI control
let chatUI: ChatUI = new ChatUI({
    messages: chatMessages,
    user: currentUserModel,
    footerTemplate: footerTemplate
});

// Render initialized Chat UI.
chatUI.appendTo('#footerTemplate');

function footerTemplate(): string {
    return `
        <div class="custom-footer">
            <input id="chatTextArea" class="e-input" placeholder="Type your message..."></input>
            <button id="sendMessage" class="e-btn e-primary e-icons e-send-1"></button>
        </div>`;
}

document.addEventListener('click', (event) => {
    if (event.target && (event.target as HTMLElement).id === 'sendMessage') {
        const textArea = document.getElementById('chatTextArea') as HTMLTextAreaElement;
        if (textArea && textArea.value.length > 0) {
            let value: string = textArea.value;
            textArea.value = '';
            chatUI.addMessage(
                {
                    author: michaleUserModel,
                    text: value
                }
            );
        }
    }
});
<!DOCTYPE html>
<html lang="en">

<head>
    <title>EJ2 Chat UI</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="TypeScript Chat UI Control" />
    <meta name="author" content="Syncfusion" />
    <link href="index.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/30.1.37/ej2-base/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/30.1.37/ej2-inputs/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/30.1.37/ej2-buttons/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/30.1.37/ej2-navigations/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/30.1.37/ej2-popups/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/30.1.37/ej2-interactive-chat/styles/material.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
    <script src="systemjs.config.js"></script>
    <style>
        #footerTemplate.e-chat-ui .e-footer {
            margin: unset;
            align-self: auto;
        }
        .custom-footer {
            display: flex;
            gap: 10px;
            padding: 10px;
            background-color: transparent;
        }
        #chatTextArea {
            width: 100%;
            border-radius: 5px;
            border: 1px solid #ccc;
            margin-bottom: 0;
            padding: 5px;
        }
        .e-icons.e-send-1 {
            font-family: "e-icons";
        }
    </style>
<script src="https://cdn.syncfusion.com/ej2/syncfusion-helper.js" type ="text/javascript"></script>
</head>
<body>
    <div id='loader'>Loading....</div>
    <div id='container' style="height: 380px; width: 450px;">
        <div id="footerTemplate"></div>
    </div>
</body>
</html>
#container {
    visibility: hidden;
    margin: 20px auto;
}

#loader {
    color: #008cff;
    height: 40px;
    left: 45%;
    position: absolute;
    top: 45%;
    width: 30%;
}