Search results

Customize ListView with dynamic tags

You can customize the ListView items using the template property. Here, the dynamic tags are added and removed in the list item from another ListView. Refer to the following steps to achieve this.

  • Render the ListView with data source, and add button element with each list item of ListView on actionComplete event. Refer to the following code sample of actionComplete event.
// The actionComplete event for first ListView to add the button

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]);
    }
}
// The actionComplete event for first ListView to add the button
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 = 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
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 = this.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);
    this.listviewInstance.element.querySelector('.e-active').appendChild(tag);
}
//Select the event that is is rendered inside dialog for ListView
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 = this.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);
    this.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
renderDialog(id) {
    if (document.getElementsByClassName('e-popup-open').length !== 0) {
        this.dialogInstance.hide();
    }
    else {
         let listElem: any = 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 = this.datasource[id];
        listIns.fields = this.fields;
        listIns.addEventListener('select', ()=> { this.addTag(event);});
        listIns.dataBind();
        listIns.appendTo(listElem);
        this.dialogInstance.position = { X: document.querySelector('.e-add-icon').getBoundingClientRect().left + 50, Y: document.querySelector('.e-add-icon').getBoundingClientRect().top - 5 };
        this.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
removeTag() {
    this.parentNode.parentNode.remove();
}
//Method to hide/show the dialog and update the ListView data source
renderDialog(id);
{
    if (document.getElementsByClassName('e-popup-open').length !== 0) {
        this.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 = this.datasource[id];
            listIns.fields = this.fields;
            listIns.addEventListener('select', () => { this.addTag(event); });
            listIns.dataBind();
            listIns.appendTo(listElem);
            this.dialogInstance.position = { X: document.querySelector('.e-add-icon').getBoundingClientRect().left + 50, Y: document.querySelector('.e-add-icon').getBoundingClientRect().top - 5 };
            this.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
    removeTag();
{
    this.parentNode.parentNode.remove();
}
Source
Preview
index.tsx
index.html
index.css
index.jsx
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';

export default class App extends React.Component<{}, {}> {
    //Define an array of JSON data
   public data: string[] =  [{ "Id": "Brooke", "Name": "Brooke" },
{ "Id": "Claire", "Name": "Claire" },
{ "Id": "Erik", "Name": "Erik" },
{ "Id": "Grace", "Name": "Grace" },
{ "Id": "Jacob", "Name": "Jacob" }];

public fields: Object = {text: "Name"};
public position: Object;
public animation: Object = {effect: 'None'};
public dialogInstance : DialogComponent;
public listObj: ListViewComponent;
public 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" },
];

public claireTag : Object = [{ "id": "list21", "Name": "Songs" },
{ "id": "list22", "Name": "Bestselling Albums" },
{ "id": "list23", "Name": "New Releases" },
{ "id": "list24", "Name": "Bestselling Songs" },
];

public 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" }
];

public graceTag : Object = [{ "id": "list41", "Name": "Rock" },
{ "id": "list42", "Name": "Gospel" },
{ "id": "list43", "Name": "Latin Music" },
{ "id": "list44", "Name": "Jazz" },
];

public jacobTag: Object = [{ "id": "list51", "Name": "100 Albums - $5 Each" },
{ "id": "list52", "Name": "Hip-Hop and R&B Sale" },
{ "id": "list53", "Name": "CD Deals" }
];

public datasource: any = { "Brooke": this.brookeTag, "Claire": this.claireTag, "Erik": this.erikTag, "Grace": this.graceTag, "Jacob": this.jacobTag };

renderDialog(id) {
    if (document.getElementsByClassName('e-popup-open').length !== 0) {
        this.dialogInstance.hide();
    }
    else {
         let listElem: any = 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 = this.datasource[id];
        listIns.fields = this.fields;
        listIns.addEventListener('select', ()=> { this.addTag(event);});
        listIns.dataBind();
        listIns.appendTo(listElem);
        this.dialogInstance.position = { X: document.querySelector('.e-add-icon').getBoundingClientRect().left + 50, Y: document.querySelector('.e-add-icon').getBoundingClientRect().top - 5 };
        this.dialogInstance.show();
        }
    }
}
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 = this.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);
    this.listviewInstance.element.querySelector('.e-active').appendChild(tag);
}
removeTag() {
    this.parentNode.parentNode.remove();
}

listtemplate(data: any): JSX.Element {
    return (
        <div>
          <span className ="templatetext">{data.Name}</span>
          <span className ="designationstyle">
          <ButtonComponent id={data.Id} className='e-but'></ButtonComponent>
          </span>
        </div>
    )};

content(data: any): JSX.Element {
    return (
        <ListViewComponent id='list' showHeader= { true } headerTitle='Favorite' width= {'200px'}></ListViewComponent>
    )
}

addButton(args:any) {
    let buttonObj: any = { 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]);
    }
    for (var i = 0; i < this.data.length; i++) {
        if(document.getElementById(this.data[i].Id)){
            document.getElementById(this.data[i].Id).addEventListener("click", (e) => {
            this.renderDialog(e.currentTarget.id);
            });
        }
    }
}

    render() {
        return (
            <div id="sample">
            <ListViewComponent id='template-list' dataSource={this.data} fields={this.fields} width= { this.width} template= {this.listtemplate as any} actionComplete = {this.addButton.bind(this)} ref={(scope) => { this.listviewInstance = scope; }} ></ListViewComponent>
             <DialogComponent id ='dialog' animationSettings={this.animation as any}
               content= {this.content as any}
               visible= {false}
               ref={dialog => this.dialogInstance = dialog}
               width= {'200px'}
               showCloseIcon= { true }
               position={this.position}
             ></DialogComponent>
            </div>
        )
    }
}
ReactDOM.render(<App />, document.getElementById('element'));
<!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="//cdn.syncfusion.com/ej2/ej2-base/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-react-lists/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-react-buttons/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/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>
</head>

<body>
    <div id='element'>
        <div id='loader'>Loading....</div>
    </div>
</body>

</html>
#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;
}
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';
export default class App extends React.Component {
    constructor() {
        super(...arguments);
        //Define an array of JSON data
        this.data = [{ "Id": "Brooke", "Name": "Brooke" },
            { "Id": "Claire", "Name": "Claire" },
            { "Id": "Erik", "Name": "Erik" },
            { "Id": "Grace", "Name": "Grace" },
            { "Id": "Jacob", "Name": "Jacob" }];
        this.fields = { text: "Name" };
        this.animation = { effect: 'None' };
        this.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" },
        ];
        this.claireTag = [{ "id": "list21", "Name": "Songs" },
            { "id": "list22", "Name": "Bestselling Albums" },
            { "id": "list23", "Name": "New Releases" },
            { "id": "list24", "Name": "Bestselling Songs" },
        ];
        this.erikTag = [{ "id": "list31", "Name": "Artwork" },
            { "id": "list32", "Name": "Abstract" },
            { "id": "list33", "Name": "Acrylic Mediums" },
            { "id": "list34", "Name": "Creative Acrylic" },
            { "id": "list35", "Name": "Canvas Art" }
        ];
        this.graceTag = [{ "id": "list41", "Name": "Rock" },
            { "id": "list42", "Name": "Gospel" },
            { "id": "list43", "Name": "Latin Music" },
            { "id": "list44", "Name": "Jazz" },
        ];
        this.jacobTag = [{ "id": "list51", "Name": "100 Albums - $5 Each" },
            { "id": "list52", "Name": "Hip-Hop and R&B Sale" },
            { "id": "list53", "Name": "CD Deals" }
        ];
        this.datasource = { "Brooke": this.brookeTag, "Claire": this.claireTag, "Erik": this.erikTag, "Grace": this.graceTag, "Jacob": this.jacobTag };
    }
    renderDialog(id) {
        if (document.getElementsByClassName('e-popup-open').length !== 0) {
            this.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 = this.datasource[id];
                listIns.fields = this.fields;
                listIns.addEventListener('select', () => { this.addTag(event); });
                listIns.dataBind();
                listIns.appendTo(listElem);
                this.dialogInstance.position = { X: document.querySelector('.e-add-icon').getBoundingClientRect().left + 50, Y: document.querySelector('.e-add-icon').getBoundingClientRect().top - 5 };
                this.dialogInstance.show();
            }
        }
    }
    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 = this.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);
        this.listviewInstance.element.querySelector('.e-active').appendChild(tag);
    }
    removeTag() {
        this.parentNode.parentNode.remove();
    }
    listtemplate(data) {
        return (<div>
          <span className="templatetext">{data.Name}</span>
          <span className="designationstyle">
          <ButtonComponent id={data.Id} className='e-but'></ButtonComponent>
          </span>
        </div>);
    }
    ;
    content(data) {
        return (<ListViewComponent id='list' showHeader={true} headerTitle='Favorite' width={'200px'}></ListViewComponent>);
    }
    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 = 0; i < ele.length; i++) {
            buttonObj.obj = new ButtonComponent(buttonObj.prop);
            buttonObj.obj.appendTo(ele[i]);
        }
        for (var i = 0; i < this.data.length; i++) {
            if (document.getElementById(this.data[i].Id)) {
                document.getElementById(this.data[i].Id).addEventListener("click", (e) => {
                    this.renderDialog(e.currentTarget.id);
                });
            }
        }
    }
    render() {
        return (<div id="sample">
            <ListViewComponent id='template-list' dataSource={this.data} fields={this.fields} width={this.width} template={this.listtemplate} actionComplete={this.addButton.bind(this)} ref={(scope) => { this.listviewInstance = scope; }}></ListViewComponent>
             <DialogComponent id='dialog' animationSettings={this.animation} content={this.content} visible={false} ref={dialog => this.dialogInstance = dialog} width={'200px'} showCloseIcon={true} position={this.position}></DialogComponent>
            </div>);
    }
}
ReactDOM.render(<App />, document.getElementById('element'));