Contact Support
Customize ListView with dynamic tags in React ListView component
23 Jan 202524 minutes to read
You can customize the ListView items using the template
property. In this example, dynamic tags are added to and removed from list items using another ListView. Follow these steps to achieve this:
-
Render the ListView with a data source, and add a button element to each list item using the
actionComplete
event. Refer to the following code sample for the actionComplete event:// The actionComplete event for first ListView to add the button function addButton(args) { let buttonObj = { obj: ButtonComponent, prop: { iconCss: 'e-icons e-add-icon', cssClass: 'e-small e-round' } }; let ele = document.getElementsByClassName("e-but"); for (let i: number = 0; i < ele.length; i++) { buttonObj.obj = new ButtonComponent(buttonObj.prop); buttonObj.obj.appendTo(ele[i]); } }
-
Initialize dynamic ListView with required property that holds the tags of parent ListView, and bind the
select
event (triggers when the list item is selected), in which you can get and add the selected item value as tags into parent ListView. Refer to the following code sample.//Select the event that is is rendered inside dialog for ListView function addTag(e) { let listTag = document.createElement('span'); listTag.className = 'advanced-option'; let labelElem = document.createElement('span'); labelElem.className = 'label'; let deleteElem = document.createElement('span'); deleteElem.className = 'delete'; deleteElem.onclick = removeTag; labelElem.innerHTML = e.target.textContent; listTag.appendChild(labelElem); listTag.appendChild(deleteElem); let tag = document.createElement('span'); tag.className = 'advanced-option-list'; tag.appendChild(listTag); listviewInstance.element.querySelector('.e-active').appendChild(tag); }
-
Render the dialog component with empty content and append the created dynamic ListView object to the dialog on
created
event. -
Bind the click event for button icon (+) to update the ListView data source with tags, and open the dialog with this dynamic ListView. Refer to the following code sample.
//Method to hide/show the dialog and update the ListView data source function renderDialog(id) { if (document.getElementsByClassName('e-popup-open').length !== 0) { dialogInstance.hide(); } else { let listElem = document.getElementById('dialog').querySelector("#list"); let listIns = document.getElementById('dialog').querySelector("#list") && document.getElementById('dialog').querySelector("#list").ej2_instances && document.getElementById('dialog').querySelector("#list").ej2_instances[0] ? document.getElementById('dialog').querySelector("#list").ej2_instances[0] : undefined; if (listIns) { listIns.dataSource = datasource[id]; listIns.fields = fields; listIns.addEventListener('select', () => { addTag(event); }); listIns.dataBind(); listIns.appendTo(listElem); dialogInstance.position = { X: document.querySelector('.e-add-icon').getBoundingClientRect().left + 50, Y: document.querySelector('.e-add-icon').getBoundingClientRect().top - 5 }; dialogInstance.show(); } } }
-
Bind the click event with added dynamic tags to remove it. Refer to the following code sample.
//Method to remove the list item function removeTag() { parentNode.parentNode.remove(); }
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';
import { DialogComponent } from '@syncfusion/ej2-react-popups';
import { EventHandler } from "@syncfusion/ej2-base";
import './index.css';
function App() {
//Define an array of JSON data
let data = [
{ Id: "Brooke", Name: "Brooke" },
{ Id: "Claire", Name: "Claire" },
{ Id: "Erik", Name: "Erik" },
{ Id: "Grace", Name: "Grace" },
{ Id: "Jacob", Name: "Jacob" }
];
let fields = { text: "Name" };
let position = null;
let animation = { effect: "None" };
let dialogInstance = null;
let listviewInstance = null;
let brookeTag = [
{ id: "list11", Name: "Discover Music" },
{ id: "list12", Name: "Sales and Events" },
{ id: "list13", Name: "Categories" },
{ id: "list14", Name: "MP3 Albums" },
{ id: "list15", Name: "More in Music" }
];
let claireTag = [
{ id: "list21", Name: "Songs" },
{ id: "list22", Name: "Bestselling Albums" },
{ id: "list23", Name: "New Releases" },
{ id: "list24", Name: "Bestselling Songs" }
];
let erikTag = [
{ id: "list31", Name: "Artwork" },
{ id: "list32", Name: "Abstract" },
{ id: "list33", Name: "Acrylic Mediums" },
{ id: "list34", Name: "Creative Acrylic" },
{ id: "list35", Name: "Canvas Art" }
];
let graceTag = [
{ id: "list41", Name: "Rock" },
{ id: "list42", Name: "Gospel" },
{ id: "list43", Name: "Latin Music" },
{ id: "list44", Name: "Jazz" }
];
let jacobTag = [
{ id: "list51", Name: "100 Albums" },
{ id: "list52", Name: "Hip-Hop and R&B Sale" },
{ id: "list53", Name: "CD Deals" }
];
let datasource = {
Brooke: brookeTag,
Claire: claireTag,
Erik: erikTag,
Grace: graceTag,
Jacob: jacobTag
};
let dialogListInstance;
function renderDialog(id) {
if (document.getElementsByClassName("e-popup-open").length !== 0) {
if (dialogInstance)
dialogInstance.hide();
}
if (dialogInstance) {
let listElem = dialogInstance.element.querySelector("#list");
dialogListInstance =
listElem && listElem.ej2_instances && listElem.ej2_instances[0]
? listElem.ej2_instances[0]
: undefined;
if (dialogListInstance) {
EventHandler.remove(dialogListInstance, "select", addTag);
dialogListInstance.dataSource = datasource[id];
dialogListInstance.fields = fields;
EventHandler.add(dialogListInstance, "select", addTag, this);
dialogListInstance.appendTo(listElem);
dialogListInstance.dataBind();
dialogInstance.position = {
X: listviewInstance.element.querySelector(".e-add-icon").getBoundingClientRect()
.left + 50,
Y: listviewInstance.element.querySelector(".e-add-icon").getBoundingClientRect()
.top - 5
};
dialogInstance.show();
}
}
}
function addTag(e) {
let listTag = document.createElement("span");
listTag.className = "advanced-option";
let labelElem = document.createElement("span");
labelElem.className = "label";
let deleteElem = document.createElement("span");
deleteElem.className = "delete";
deleteElem.onclick = removeTag;
labelElem.innerHTML = e.text;
listTag.appendChild(labelElem);
listTag.appendChild(deleteElem);
let tag = document.createElement("span");
tag.className = "advanced-option-list";
tag.appendChild(listTag);
listviewInstance.element.querySelector(".e-active").appendChild(tag);
}
function removeTag() {
this.parentNode.parentNode.remove();
}
function handleClick(e) {
renderDialog(e.currentTarget.id);
}
function listtemplate(data) {
return (<div>
<span className="templatetext">{data.Name}</span>
<span className="designationstyle">
<ButtonComponent id={data.Id} className="e-but e-small e-round" iconCss={"e-icons e-add-icon"} onClick={handleClick.bind(this)} />
</span>
</div>);
}
function dialogContent() {
return <ListViewComponent id="list" showHeader={true} headerTitle="Favorite" width={"200px"} />;
}
return (<div id="sample">
<ListViewComponent id="template-list" dataSource={data} fields={fields} template={listtemplate.bind(this)} ref={scope => {
listviewInstance = scope;
}} />
<DialogComponent id="dialog" animationSettings={animation} content={dialogContent} visible={false} ref={dialog => (dialogInstance = dialog)} width={"200px"} showCloseIcon={true} position={position} />
</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';
import { DialogComponent } from '@syncfusion/ej2-react-popups';
import { Browser, EventHandler } from "@syncfusion/ej2-base";
function App() {
//Define an array of JSON data
let data: any[] = [
{ Id: "Brooke", Name: "Brooke" },
{ Id: "Claire", Name: "Claire" },
{ Id: "Erik", Name: "Erik" },
{ Id: "Grace", Name: "Grace" },
{ Id: "Jacob", Name: "Jacob" }
];
let fields: object = { text: "Name" };
let position: any = null;
let animation: object = { effect: "None" };
let dialogInstance: DialogComponent | null = null;
let listviewInstance: ListViewComponent | null = null;
let brookeTag: object[] = [
{ id: "list11", Name: "Discover Music" },
{ id: "list12", Name: "Sales and Events" },
{ id: "list13", Name: "Categories" },
{ id: "list14", Name: "MP3 Albums" },
{ id: "list15", Name: "More in Music" }
];
let claireTag: object[] = [
{ id: "list21", Name: "Songs" },
{ id: "list22", Name: "Bestselling Albums" },
{ id: "list23", Name: "New Releases" },
{ id: "list24", Name: "Bestselling Songs" }
];
let erikTag: object[] = [
{ id: "list31", Name: "Artwork" },
{ id: "list32", Name: "Abstract" },
{ id: "list33", Name: "Acrylic Mediums" },
{ id: "list34", Name: "Creative Acrylic" },
{ id: "list35", Name: "Canvas Art" }
];
let graceTag: object[] = [
{ id: "list41", Name: "Rock" },
{ id: "list42", Name: "Gospel" },
{ id: "list43", Name: "Latin Music" },
{ id: "list44", Name: "Jazz" }
];
let jacobTag: object[] = [
{ id: "list51", Name: "100 Albums" },
{ id: "list52", Name: "Hip-Hop and R&B Sale" },
{ id: "list53", Name: "CD Deals" }
];
let datasource: any = {
Brooke: brookeTag,
Claire: claireTag,
Erik: erikTag,
Grace: graceTag,
Jacob: jacobTag
};
let dialogListInstance: any;
function renderDialog(id: any) {
if (document.getElementsByClassName("e-popup-open").length !== 0) {
if (dialogInstance) dialogInstance.hide();
}
if (dialogInstance) {
let listElem: any = dialogInstance.element.querySelector("#list");
dialogListInstance =
listElem && listElem.ej2_instances && listElem.ej2_instances[0]
? listElem.ej2_instances[0]
: undefined;
if (dialogListInstance) {
EventHandler.remove(dialogListInstance, "select", addTag);
dialogListInstance.dataSource = datasource[id];
dialogListInstance.fields = fields;
EventHandler.add(dialogListInstance, "select", addTag, this);
dialogListInstance.appendTo(listElem);
dialogListInstance.dataBind();
dialogInstance.position = {
X:
(listviewInstance as any).element.querySelector(".e-add-icon").getBoundingClientRect()
.left + 50,
Y:
(listviewInstance as any).element.querySelector(".e-add-icon").getBoundingClientRect()
.top - 5
};
dialogInstance.show();
}
}
}
function addTag(e: any) {
let listTag = document.createElement("span");
listTag.className = "advanced-option";
let labelElem = document.createElement("span");
labelElem.className = "label";
let deleteElem = document.createElement("span");
deleteElem.className = "delete";
deleteElem.onclick = removeTag;
labelElem.innerHTML = e.text;
listTag.appendChild(labelElem);
listTag.appendChild(deleteElem);
let tag = document.createElement("span");
tag.className = "advanced-option-list";
tag.appendChild(listTag);
(listviewInstance as any).element.querySelector(".e-active").appendChild(tag);
}
function removeTag() {
(this as any).parentNode.parentNode.remove();
}
function handleClick(e: any) {
renderDialog(e.currentTarget.id);
}
function listtemplate(data: any): JSX.Element {
return (
<div>
<span className="templatetext">{data.Name}</span>
<span className="designationstyle">
<ButtonComponent
id={data.Id}
className="e-but e-small e-round"
iconCss={"e-icons e-add-icon"}
onClick={handleClick.bind(this)}
/>
</span>
</div>
);
}
function dialogContent(): JSX.Element {
return <ListViewComponent id="list" showHeader={true} headerTitle="Favorite" width={"200px"} />;
}
return (
<div id="sample">
<ListViewComponent
id="template-list"
dataSource={data}
fields={fields}
template={listtemplate.bind(this) as any}
ref={scope => {
listviewInstance = scope;
}}
/>
<DialogComponent
id="dialog"
animationSettings={animation as any}
content={dialogContent as any}
visible={false}
ref={dialog => (dialogInstance = dialog)}
width={"200px"}
showCloseIcon={true}
position={position}
/>
</div>
);
}
export default App;
ReactDOM.render(<App />, document.getElementById('element'));
#loader {
color: #008cff;
height: 40px;
width: 30%;
position: absolute;
font-family: "Helvetica Neue", "calibiri";
font-size: 14px;
top: 45%;
left: 45%;
}
#sample {
padding: 40px;
}
.advanced-option-list {
display: inline-flex;
list-style: none;
margin: 0;
padding: 0;
margin-top: 4px;
overflow: auto;
}
.advanced-option {
border: 1px solid #0078d7;
-webkit-border-radius: 2px;
-moz-border-radius: 2px;
border-radius: 2px;
padding: 0 20px 0 5px;
margin: 0 3px 1px 0;
float: left;
position: relative;
background: white;
line-height: 21px;
}
.advanced-option .label {
color: #0078d7;
font-size: 10px;
}
.advanced-option .delete {
background: url(https://research.isg-one.com/Assets/img/Content/icn/tiny-del.png) right center no-repeat;
padding-left: 10px;
padding-top: 2px;
right: 0;
position: absolute;
top: 1px;
cursor: pointer;
height: 16px;
width: 30px;
}
#template-list {
max-width: 350px;
margin: auto;
border: 1px solid #dddddd;
border-radius: 3px;
}
#template-list .designationstyle {
float: right;
position: relative;
right: 10px;
}
.cont-bg {
font-size: 17px;
height: 46px;
padding-top: 10px;
width: 100%;
}
.e-add-icon::before {
content: "\e823";
}
#template-list .e-list-item {
height: auto;
padding: 11px 16px;
}
.e-dialog .e-dlg-header-content+.e-dlg-content {
margin-top: -18px;
padding-top: 15px;
}
.e-lib.e-dialog.e-popup .e-dlg-header-content {
z-index: 1000;
position: absolute;
right: 0;
top: -28px;
background: transparent;
}
<!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-react-lists/styles/material.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/29.1.33/ej2-react-buttons/styles/material.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/29.1.33/ej2-react-popups/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'>
<div id='loader'>Loading....</div>
</div>
</body>
</html>