Contact Support
Customize ListView with dynamic tags in Angular ListView component
22 Apr 202516 minutes to read
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.
-
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.text; 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.dialog.hide(); } else { this.listObj.dataSource = this.datasource[id]; this.listObj.dataBind(); this.dialog.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(); }
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { ListViewModule } from '@syncfusion/ej2-angular-lists'
import { DialogModule } from '@syncfusion/ej2-angular-popups'
import { ButtonModule } from '@syncfusion/ej2-angular-buttons'
import { Component, ViewChild } from '@angular/core';
import { ListViewComponent } from "@syncfusion/ej2-angular-lists";
import { DialogComponent } from "@syncfusion/ej2-angular-popups";
import { CommonModule } from '@angular/common';
@Component({
imports: [
ListViewModule,
DialogModule,
ButtonModule,
CommonModule
],
standalone: true,
selector: 'my-app',
template: `
<div id="sample">
<ejs-listview #list id='templatelist' [dataSource]='data' [fields]='fields' width=350>
<ng-template #template let-data="">
<div>
<span class="templatetext"></span>
<span class="designationstyle">
<button ejs-button [id]="data.Id" class="e-but" iconCss='e-icons e-add-icon' cssClass='e-small e-round' (click)='onClick($event)'></button>
</span>
<span class="advanced-option-list">
<span *ngFor="let tag of data.tags" class="advanced-option">
<span class="label"></span>
<span class="e-icons e-close" (click)="removeTag(data, tag)"></span>
</span>
</span>
</div>
</ng-template>
</ejs-listview>
<ejs-dialog id='dialog' #ejDialog width='200px' [animationSettings]='animation' [visible]='false' showCloseIcon='true' [position]='position'>
<ng-template #content>
<ejs-listview #List id="list" showHeader=true headerTitle='Favorite' width='200px' [dataSource]='datasource[currentSelectedId]' [fields]='fields' (select)='addTag($event)'></ejs-listview>
</ng-template>
</ejs-dialog>
</div>
`
})
export class AppComponent {
@ViewChild('list') listViewInstance?: ListViewComponent;
@ViewChild('List') listObj?: ListViewComponent;
@ViewChild('ejDialog') dialog?: DialogComponent;
public data: any[] = [
{ "Id": "Brooke", "Name": "Brooke", tags: [] },
{ "Id": "Claire", "Name": "Claire", tags: [] },
{ "Id": "Erik", "Name": "Erik", tags: [] },
{ "Id": "Grace", "Name": "Grace", tags: [] },
{ "Id": "Jacob", "Name": "Jacob", tags: [] }
];
public fields: Object = { text: "Name" };
public position?: Object;
public animation: Object = { effect: 'None' };
public currentSelectedId: string = '';
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" },
{ "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
};
ngAfterViewChecked() {
setTimeout(() => {
this.position = {
X: (document.querySelector('.e-add-icon') as HTMLElement | any).getBoundingClientRect().left + 50,
Y: (document.querySelector('.e-add-icon') as any).getBoundingClientRect().top - 5
};
}, 1000);
}
onClick(e: any) {
this.currentSelectedId = e.currentTarget.id;
this.renderDialog(this.currentSelectedId);
}
renderDialog(id: string | number) {
if (document.getElementsByClassName('e-popup-open').length != 0) {
(this.dialog as DialogComponent).hide();
} else {
(this.listObj as ListViewComponent).dataSource = this.datasource[id];
this.listObj?.dataBind();
(this.dialog as DialogComponent).show();
}
}
addTag(e: any) {
const selectedItem = this.data.find(item => item.Id === this.currentSelectedId);
if (selectedItem && !selectedItem.tags.includes(e.text)) {
selectedItem.tags.push(e.text);
this.listViewInstance?.refresh();
}
this.dialog?.hide();
}
removeTag(item: any, tag: string) {
const index = item.tags.indexOf(tag);
if (index > -1) {
item.tags.splice(index, 1);
this.listViewInstance?.refresh();
}
}
}
@import 'node_modules/@syncfusion/ej2-base/styles/material.css';
@import 'node_modules/@syncfusion/ej2-angular-base/styles/material.css';
@import 'node_modules/@syncfusion/ej2-angular-lists/styles/material.css';
@import 'node_modules/@syncfusion/ej2-angular-buttons/styles/material.css';
@import 'node_modules/@syncfusion/ej2-angular-popups/styles/material.css';
#sample {
padding: 40px;
}
.advanced-option-list {
display: inline-flex;
list-style: none;
margin-left: 5px;
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 .e-icons.e-close {
right: 0;
position: absolute;
top: 6px;
cursor: pointer;
width: 14px;
font-size: xx-small;
}
#templatelist .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';
}
#templatelist .e-list-item {
height: auto;
}
.e-dialog .e-dlg-header-content+.e-dlg-content {
margin-top: -18px;
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));