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/29.1.33/ej2-base/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/29.1.33/ej2-buttons/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/29.1.33/ej2-react-lists/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/29.1.33/ej2-layouts/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/29.1.33/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>