Customize ListView as chat window in React ListView component
23 Jan 202524 minutes to read
The ListView can be customizable as a chat window. To achieve this, use ListView template
property and Avatar
component.
- The ListView template property is used to showcase the ListView as a chat window.
- The Avatar component is used to design the image of the contact person.
Refer the below template code snippet for Template of chat window.
function listTemplate(data: any): JSX.Element {
let sendertemplate = <div className='settings'><div id="content"><div className="name">{data.text}</div><div id="info">{data.contact}</div></div>{
data.avatar !== "" ?
<div id="image"><span className='e-avatar img1 e-avatar-circle'>{data.avatar}</span></div> : <div id="image"><span className={`${data.pic} img1 e-avatar e-avatar-circle`}></span></div>
}</div>
let receivertemplate = <div className='settings'>{
data.avatar !== "" ?
<div id="image2"><span className='e-avatar img2 e-avatar-circle'>{data.avatar}</span></div> : <div id="image2"><span className={`${data.pic} img2 e-avatar e-avatar-circle`}></span></div>
}<div id="content1"><div className="name1">{data.text}</div><div id="info1">{data.contact}</div></div></div>
return (
<div>
{data.chat !== "receiver" ? (sendertemplate) : (receivertemplate)}
</div>
);
}
function listTemplate(data) {
let sendertemplate = <div className='settings'><div id="content"><div className="name">{data.text}</div><div id="info">{data.contact}</div></div>{data.avatar !== "" ?
<div id="image"><span className='e-avatar img1 e-avatar-circle'>{data.avatar}</span></div> : <div id="image"><span className={`${data.pic} img1 e-avatar e-avatar-circle`}></span></div>}</div>;
let receivertemplate = <div className='settings'>{data.avatar !== "" ?
<div id="image2"><span className='e-avatar img2 e-avatar-circle'>{data.avatar}</span></div> : <div id="image2"><span className={`${data.pic} img2 e-avatar e-avatar-circle`}></span></div>}<div id="content1"><div className="name1">{data.text}</div><div id="info1">{data.contact}</div></div></div>;
return (<div>
{data.chat !== "receiver" ? (sendertemplate) : (receivertemplate)}
</div>);
}
Chat order in template
In the ListView template, we have rendered the list items based on receiver and sender information from dataSource of the ListView.
Adding messages to chat window
* Use textbox to get message from user.
* Add the textbox message to the ListView dataSource using [addItem](https://ej2.syncfusion.com/react/documentation/api/list-view/#additem) method.
function btnClick() {
let value = textboxEle.value;
listObj.addItem([{ text: "Amenda", contact: value, id: "2", avatar: "A", pic: "", chat: "receiver" }]);
textboxEle.value ="";
}
import * as ReactDOM from 'react-dom';
import * as React from 'react';
import { ListViewComponent } from '@syncfusion/ej2-react-lists';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
function App() {
let listObj = null;
let textboxEle;
//Define an array of JSON data
let data = [
{
text: "Jenifer",
contact: "Hi",
id: "1",
avatar: "",
pic: "pic01",
chat: "sender"
},
{ text: "Amenda", contact: "Hello", id: "2", avatar: "A", pic: "", chat: "receiver" },
{
text: "Jenifer",
contact: "What Knid of application going to launch",
id: "4",
avatar: "",
pic: "pic01",
chat: "sender"
},
{
text: "Amenda ",
contact: "A knid of Emergency broadcast App",
id: "5",
avatar: "A",
pic: "",
chat: "receiver"
},
{
text: "Jacob",
contact: "Can you please elaborate",
id: "6",
avatar: "",
pic: "pic04",
chat: "sender"
}
];
function listTemplate(data) {
const sendertemplate = (<div className="settings">
<div id="content">
<div className="name">{data.text}</div>
<div id="info">{data.contact}</div>
</div>
{data.avatar !== "" ? (<div id="image">
<span className="e-avatar img1 e-avatar-circle">{data.avatar}</span>
</div>) : (<div id="image">
<span className={`${data.pic} img1 e-avatar e-avatar-circle`} />
</div>)}
</div>);
const receivertemplate = (<div className="settings">
{data.avatar !== "" ? (<div id="image2">
<span className="e-avatar img2 e-avatar-circle">{data.avatar}</span>
</div>) : (<div id="image2">
<span className={`${data.pic} img2 e-avatar e-avatar-circle`} />
</div>)}
<div id="content1">
<div className="name1">{data.text}</div>
<div id="info1">{data.contact}</div>
</div>
</div>);
return <div>{data.chat !== "receiver" ? sendertemplate : receivertemplate}</div>;
}
function btnClick() {
const value = textboxEle.value;
listObj.addItem([
{ text: "Amenda", contact: value, id: "2", avatar: "A", pic: "", chat: "receiver" }
]);
textboxEle.value = "";
}
return (<div>
{/* ListView element */}
<ListViewComponent id="List" dataSource={data} headerTitle="Chat" showHeader={true} template={listTemplate} ref={scope => {
listObj = scope;
}} />
<input id="inputname" className="e-input" ref={textbox => {
textboxEle = textbox;
}} type="text" placeholder="Type your message" />
<ButtonComponent id="btn" onClick={btnClick.bind(this)}>
Send
</ButtonComponent>
</div>);
}
export default App;
ReactDOM.render(<App />, document.getElementById('element'));
import * as ReactDOM from 'react-dom';
import * as React from 'react';
import { ListViewComponent } from '@syncfusion/ej2-react-lists';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
function App() {
let listObj: ListViewComponent = null as any;
let textboxEle: any;
//Define an array of JSON data
let data: { [key: string]: Object }[] = [
{
text: "Jenifer",
contact: "Hi",
id: "1",
avatar: "",
pic: "pic01",
chat: "sender"
},
{ text: "Amenda", contact: "Hello", id: "2", avatar: "A", pic: "", chat: "receiver" },
{
text: "Jenifer",
contact: "What Knid of application going to launch",
id: "4",
avatar: "",
pic: "pic01",
chat: "sender"
},
{
text: "Amenda ",
contact: "A knid of Emergency broadcast App",
id: "5",
avatar: "A",
pic: "",
chat: "receiver"
},
{
text: "Jacob",
contact: "Can you please elaborate",
id: "6",
avatar: "",
pic: "pic04",
chat: "sender"
}
];
function listTemplate(data: any): JSX.Element {
const sendertemplate = (
<div className="settings">
<div id="content">
<div className="name">{data.text}</div>
<div id="info">{data.contact}</div>
</div>
{data.avatar !== "" ? (
<div id="image">
<span className="e-avatar img1 e-avatar-circle">{data.avatar}</span>
</div>
) : (
<div id="image">
<span className={`${data.pic} img1 e-avatar e-avatar-circle`} />
</div>
)}
</div>
);
const receivertemplate = (
<div className="settings">
{data.avatar !== "" ? (
<div id="image2">
<span className="e-avatar img2 e-avatar-circle">{data.avatar}</span>
</div>
) : (
<div id="image2">
<span className={`${data.pic} img2 e-avatar e-avatar-circle`} />
</div>
)}
<div id="content1">
<div className="name1">{data.text}</div>
<div id="info1">{data.contact}</div>
</div>
</div>
);
return <div>{data.chat !== "receiver" ? sendertemplate : receivertemplate}</div>;
}
function btnClick() {
const value = textboxEle.value;
listObj.addItem([
{ text: "Amenda", contact: value, id: "2", avatar: "A", pic: "", chat: "receiver" }
]);
textboxEle.value = "";
}
return (
<div>
{/* ListView element */}
<ListViewComponent
id="List"
dataSource={data}
headerTitle="Chat"
showHeader={true}
template={listTemplate as any}
ref={scope => {
listObj = scope as any;
}}
/>
<input
id="inputname"
className="e-input"
ref={textbox => {
textboxEle = textbox;
}}
type="text"
placeholder="Type your message"
/>
<ButtonComponent id="btn" onClick={btnClick.bind(this)}>
Send
</ButtonComponent>
</div>
);
}
export default App;
ReactDOM.render(<App />, document.getElementById('element'));
#List {
margin: 0 auto;
border: 1px solid #ccc;
}
#List .e-list-item {
height: auto;
cursor: pointer;
}
#List .e-list-header .e-text {
font-family: sans-serif;
font-size: 18px;
line-height: 26px;
}
#List #info,
#List .name {
font-size: 11px;
line-height: 20px;
}
#List .name {
padding-top: 3px;
font-weight: 500;
padding-left: 150px;
margin-left: 55px;
}
#List #info {
float: right;
margin-right: 10px;
}
.pic01 {
background-image: url("https://ej2.syncfusion.com/demos/src/grid/images/1.png");
}
.pic02 {
background-image: url("https://ej2.syncfusion.com/demos/src/grid/images/3.png");
}
.pic03 {
background-image: url("https://ej2.syncfusion.com/demos/src/grid/images/5.png");
}
.pic04 {
background-image: url("https://ej2.syncfusion.com/demos/src/grid/images/2.png");
}
.img2 {
margin-left: 10px;
margin-top: 7px;
font-size: 13px;
}
#List #content1 {
width: 200px;
background-color: aliceblue;
display: inline-block;
margin: 5px;
}
#List #info1,
#List .name1 {
font-size: 11px;
line-height: 20px;
margin-left: 10px;
}
#List .name1 {
padding-top: 3px;
font-weight: 500;
}
#List #content {
margin: 5px;
width: 250px;
margin-left: 62px;
background-color: aliceblue;
display: inline-block
}
#image {
float: right;
}
#image2 {
float: left;
}
.img1 {
margin-right: 10px;
margin: 5px;
font-size: 13px;
}
.e-listview .e-list-header {
color: white;
}
.e-listview .e-list-header {
background: rgb(2, 120, 215);
}
#List.e-listview .e-hover {
background-color: transparent;
}
#inputname {
width: 275px
}
.message {
width: 350px;
margin: 0 auto;
}
#btn {
float: right
}
<!DOCTYPE html>
<html lang="en">
<head>
<title>Syncfusion React ListView</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Essential JS 2 for React Components" />
<meta name="author" content="Syncfusion" />
<link href="https://cdn.syncfusion.com/ej2/31.1.17/ej2-base/styles/material.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/31.1.17/ej2-buttons/styles/material.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/31.1.17/ej2-react-lists/styles/material.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/31.1.17/ej2-layouts/styles/material.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/31.1.17/ej2-inputs/styles/material.css" rel="stylesheet" />
<link href="index.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>
#loader {
color: #008cff;
height: 40px;
left: 45%;
position: absolute;
top: 45%;
width: 30%;
}
</style>
<script src="https://cdn.syncfusion.com/ej2/syncfusion-helper.js" type ="text/javascript"></script>
</head>
<body>
<div id='element' style="margin:0 auto; max-width:400px;">
<div id='loader'>Loading....</div>
</div>
<style>
#List {
margin: 0 auto;
border: 1px solid #ccc;
}
#List .e-list-item {
height: auto;
cursor: pointer;
}
#List .e-list-header .e-text {
font-family: sans-serif;
font-size: 18px;
line-height: 26px;
}
#List #info1,
#List .name1 {
margin-left: 10px;
}
#List #info,
#List .name,
#List #info1,
#List .name1 {
font-size: 11px;
line-height: 20px;
}
#List .name {
padding-left: 150px;
margin-left: 55px;
}
#List #info {
float: right;
margin-right: 10px;
}
.pic01 {
background-image: url("https://ej2.syncfusion.com/demos/src/grid/images/1.png");
}
.pic02 {
background-image: url("https://ej2.syncfusion.com/demos/src/grid/images/3.png");
}
.pic03 {
background-image: url("https://ej2.syncfusion.com/demos/src/grid/images/5.png");
}
.pic04 {
background-image: url("https://ej2.syncfusion.com/demos/src/grid/images/2.png");
}
.img2 {
margin-left: 10px;
margin-top: 7px;
font-size: 13px;
}
#List #content1 {
width: 200px;
background-color: aliceblue;
display: inline-block;
margin: 5px;
}
#List .name1,
#List .name {
padding-top: 3px;
font-weight: 500;
}
#List #content {
margin: 5px;
width: 250px;
margin-left: 62px;
background-color: aliceblue;
display: inline-block
}
#image {
float: right;
/* display: inline-block; */
}
#image2 {
float: left;
/* display: inline-block; */
}
.img1 {
margin-right: 10px;
margin: 5px;
font-size: 13px;
}
.e-listview .e-list-header {
color: white;
background: rgb(2, 120, 215);
}
#List.e-listview .e-hover {
background-color: transparent;
}
#inputname {
width: 275px
}
.message {
width: 350px;
margin: 0 auto;
}
#btn {
float: right
}
</style>
</body>
</html>