Single or many items can be selected by users in the ListView component. An API is used to get selected items from the list items. This is called as the getSelectedItems
method.
getSelectedItems
method
This is used to get the details of the currently selected item from the list items. It returns the SelectedItem
| SelectedCollection
The getSelectedItems
method returns the following items from the selected list items.
Return type | Purpose |
---|---|
text | Returns the text of selected item lists |
data | Returns the whole data of selected list items, i.e., returns the fields data of selected li. |
item | Returns the collections of list items |
import { Component,ViewChild } from '@angular/core';
@Component({
selector: 'my-app',
template: `<ejs-listview #listview id='sample-list' [dataSource]='data' [showCheckBox]=true [fields]='fields'></ejs-listview>
<br/>
<input type="button" id="btn" ejs-button value="Get Selected Items" (click)="onClick($event)" />
<div #val id="val">
</div>`
})
export class AppComponent {
@ViewChild('listview') element:any;
@ViewChild('val') valEle:any;
public data: Object = [
{ text: 'Hennessey Venom', id: 'list-01' },
{ text: 'Bugatti Chiron', id: 'list-02', isChecked: true },
{ text: 'Bugatti Veyron Super Sport', id: 'list-03'},
{ text: 'SSC Ultimate Aero', id: 'list-04', isChecked: true },
{ text: 'Koenigsegg CCR', id: 'list-05' },
{ text: 'McLaren F1', id: 'list-06' },
{ text: 'Aston Martin One- 77', id: 'list-07', isChecked: true },
{ text: 'Jaguar XJ220', id: 'list-08' }
];
public fields: Object = { id: 'id', isChecked:'isChecked'};
onClick(event: any){
let selecteditem =this.element.getSelectedItems();
this.valEle.nativeElement.innerHTML="";
for(let i=0; i< selecteditem["data"].length; i++) {
let listData = document.createElement('p');
listData.innerHTML = "text : "+ selecteditem["text"][i]+" , "+"id : "+selecteditem["data"][i].id;
this.valEle.nativeElement.append(listData);
}
}
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { ListViewModule } from '@syncfusion/ej2-angular-lists';
/**
* Module
*/
@NgModule({
imports: [
BrowserModule,
ListViewModule
],
declarations: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule { }
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { AppModule } from './app.module';
enableProdMode();
platformBrowserDynamic().bootstrapModule(AppModule);
The Syncfusion Essential JS2 components are desktop and mobile-friendly. So, you can use Syncfusion components in both modes. The component templates are not always fixed. Applications may need to load various templates depending upon the device.
In the ListView component, template support is being used. In some cases, the component wrapper is always responsive across all devices, but the template contents are dynamically changed with unspecified (sample side) dimensions. CSS customization is also needed in sample-side to align template content responsively in both mobile and desktop modes. Here, two templates have been loaded for mobile and desktop modes. To check the device mode, a browser module has been imported from the ej2-base package.
import { Component} from '@angular/core';
import { Browser } from '@syncfusion/ej2-base';
@Component({
selector: 'my-app',
template: `<ejs-listview id='List' [dataSource]='dataSource' [template]='templatecheck ? mob_template : win_template' headerTitle='Syncfusion Blog' [showHeader]='true'>
<ng-template #mob_template let-dataSource="">
<div class="settings">
<div id="postContainer">
<div id="postImg">
<img src={{dataSource.image}} /></div>
<div id="content">
<div id="info">
<div id="logo">
<div id="share">
<span class="share"></span> </div>
<div id="comments"> <span class="comments"></span> </div>
<div id="bookmark"> <span class="bookmark"></span> </div>
</div>
</div>
<div class="name">{{dataSource.Name}}</div>
<div class="description">{{dataSource.content}}</div>
<div class="timeStamp">{{dataSource.timeStamp}} </div>
</div>
</div>
</div>
</ng-template>
<ng-template #win_template let-dataSource="">
<div class="settings">
<div id="postContainer">
<div id="postImg">
<img src={{dataSource.image}} /></div>
<div id="content">
<div class="name">{{dataSource.Name}}</div>
<div class="description">{{dataSource.content}}</div>
<div id="info">
<div id="logo">
<div id="share">
<span class="share"></span> </div>
<div id="comments"> <span class="comments"></span> </div>
<div id="bookmark"> <span class="bookmark"></span> </div>
</div>
<div class="timeStamp">{{dataSource.timeStamp}} </div>
</div>
</div>
</div>
</div>
</ng-template></ejs-listview>`
})
export class AppComponent {
//Define an array of JSON data
public dataSource: any = [
{ Name: 'IBM Open-Sources Web Sphere Liberty Code', content: 'In September, IBM announced that it would be open-sourcing the code for WebSphere...', id: '1', image: 'https://ej2.syncfusion.com/demos/src/listview/images/1.png', timeStamp: 'Syncfusion Blog - October 19, 2017' },
{ Name: 'Must Reads: 5 Big Data E-books to upend your development', content: 'Our first e-book was published in May 2012-jQuery Succinctly was the start of over...', id: '2', image: 'https://ej2.syncfusion.com/demos/src/listview/images/2.png', timeStamp: 'Syncfusion Blog - October 18, 2017' },
{ Name: 'The Syncfusion Global License: Your Questions, Answered ', content: 'Syncfusion recently hosted a webinar to cover the ins and outs of the Syncfusion global...', id: '4', image: 'https://ej2.syncfusion.com/demos/src/listview/images/3.png', timeStamp: 'Syncfusion Blog - October 18, 2017' },
{ Name: 'Know: What is Coming from Microsoft this Fall ', content: 'On October 17, Microsoft will release its Fall Creators Update for the Windows 10 platform...', id: '5', image: 'https://ej2.syncfusion.com/demos/src/listview/images/6.png', timeStamp: 'Syncfusion Blog - October 17, 2017' }
];
public fields: Object = { text: 'Name' };
public templatecheck:Boolean;
constructor(){
this.templatecheck = Browser.isDevice;
}
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { ListViewModule } from '@syncfusion/ej2-angular-lists';
/**
* Module
*/
@NgModule({
imports: [
BrowserModule,
ListViewModule
],
declarations: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule { }
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { AppModule } from './app.module';
enableProdMode();
platformBrowserDynamic().bootstrapModule(AppModule);
To load list items in child list dynamically, push the new list item data into the existing dataSource
using the select
event.
Refer to the following steps to load list item into the child list:
select
event that triggers selecting list item in the ListView component. By using the select event, you can push the new list item to the child list of the data source on specifying its item index. Item index can be obtained from the SelectEventArgs
of the select event.import { Component, ViewEncapsulation } from '@angular/core';
import { SelectEventArgs } from '@syncfusion/ej2-lists';
@Component({
selector: 'my-app',
template: `<ejs-listview id='listview' [dataSource]='dataSource' [template]='wintemplate' headerTitle='Folders' [showHeader]='true' [showIcon]='true' [fields]='fields' (select)='onSelect($event)'></ejs-listview>
`,
styles: [`
#listview {
display: block;
max-width: 400px;
margin: auto;
border: 1px solid #dddddd;
border-radius: 3px;
}
#listview.e-listview .e-list-icon {
height: 24px;
width: 30px;
}
.folder, .file {
background: url('http://ej2.syncfusion.com/demos/src/listview/images/file_icons.png') no-repeat;
background-size: 300%;
}
.folder{
background-position: -5px -460px;
}
.file {
background-position: -5px -151px;
}
.list {
color:deeppink !important;
}
`],
encapsulation: ViewEncapsulation.None
})
export class AppComponent {
public dataSource: { [key: string]: Object }[] = [
{
id: '01', text: 'Music', icon: 'folder',
child: [
{ id: '01-01', text: 'Gouttes.mp3', icon: 'file' }
]
},
{
id: '02', text: 'Videos', icon: 'folder',
child: [
{ id: '02-01', text: 'Naturals.mp4', icon: 'file' },
{ id: '02-02', text: 'Wild.mpeg', icon: 'file' },
]
},
{
id: '03', text: 'Documents', icon: 'folder',
child: [
{ id: '03-01', text: 'Environment Pollution.docx', icon: 'file' },
{ id: '03-02', text: 'Global Water, Sanitation, & Hygiene.docx', icon: 'file' },
{ id: '03-03', text: 'Global Warming.ppt', icon: 'file' },
{ id: '03-04', text: 'Social Network.pdf', icon: 'file' },
{ id: '03-05', text: 'Youth Empowerment.pdf', icon: 'file' },
]
},
{
id: '04', text: 'Pictures', icon: 'folder',
child: [
{
id: '04-01', text: 'Camera Roll', icon: 'folder',
child: [
{ id: '04-01-01', text: 'WIN_20160726_094117.JPG', icon: 'file' },
{ id: '04-01-02', text: 'WIN_20160726_094118.JPG', icon: 'file' },
{ id: '04-01-03', text: 'WIN_20160726_094119.JPG', icon: 'file' }
]
},
{
id: '04-02', text: 'Wind.jpg', icon: 'file'
},
{
id: '04-02', text: 'Stone.jpg', icon: 'file'
},
{
id: '04-02', text: 'Home.jpg', icon: 'file'
},
{
id: '04-02', text: 'Bridge.png', icon: 'file'
}
]
},
{
id: '05', text: 'Downloads', icon: 'folder',
child: [
{ id: '05-01', text: 'UI-Guide.pdf', icon: 'file' },
{ id: '05-02', text: 'Tutorials.zip', icon: 'file' },
{ id: '05-03', text: 'Game.exe', icon: 'file' },
{ id: '05-04', text: 'TypeScript.7z', icon: 'file' },
]
},
];
public fields: Object = { iconCss: 'icon', tooltip: 'text' };
//Select event to add new list item in child page
onSelect(args: SelectEventArgs) {
//Add new file to the child page of selected list item
(this.dataSource[args.index].child as Object[]).push({ id: '01-02', text: 'Newly Added File', icon: 'file', htmlAttributes: { role: 'li', class: 'list' } });
}
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { ListViewModule } from '@syncfusion/ej2-angular-lists';
/**
* Module
*/
@NgModule({
imports: [
BrowserModule,
ListViewModule
],
declarations: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule { }
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { AppModule } from './app.module';
enableProdMode();
platformBrowserDynamic().bootstrapModule(AppModule);
The ListView component supports wrapping list items into a group based on the category. The category of each list item can be mapped with groupBy field of the data source. You can display grouped list items count in the list-header using the group header template. Refer to the following code sample to display grouped list item count.
import { Component} from '@angular/core';
@Component({
selector: 'my-app',
template: `<ejs-listview id='List' [dataSource]='dataSource' cssClass='e-list-template' [fields]='fields'>
<ng-template #template let-dataSource="">
<div class="e-list-wrapper e-list-multi-line e-list-avatar">
<img class="e-avatar e-avatar-circle" src={{dataSource.image}} style="background:#BCBCBC" />
<span class="e-list-item-header">{{dataSource.Name}}</span>
<span class="e-list-content">{{dataSource.contact}}</span>
</div>
</ng-template>
</ejs-listview>`
})
export class AppComponent {
public dataSource: Object = [
{ Name: 'Nancy', contact:'(206) 555-985774', id: '1', image: 'https://ej2.syncfusion.com/demos/src/grid/images/1.png', category: 'Experience'},
{ Name: 'Janet', contact: '(206) 555-3412', id: '2', image: 'https://ej2.syncfusion.com/demos/src/grid/images/3.png', category: 'Fresher' },
{ Name: 'Margaret', contact:'(206) 555-8122', id:'4', image: 'https://ej2.syncfusion.com/demos/src/grid/images/4.png', category: 'Experience' },
{ Name: 'Andrew ', contact:'(206) 555-9482', id: '5', image: 'https://ej2.syncfusion.com/demos/src/grid/images/2.png', category: 'Experience'},
{ Name: 'Steven', contact:'(71) 555-4848', id: '6', image: 'https://ej2.syncfusion.com/demos/src/grid/images/5.png', category: 'Fresher' },
{ Name: 'Michael', contact:'(71) 555-7773', id: '7', image: 'https://ej2.syncfusion.com/demos/src/grid/images/6.png', category: 'Experience' },
{ Name: 'Robert', contact:'(71) 555-5598', id: '8', image: 'https://ej2.syncfusion.com/demos/src/grid/images/7.png', category: 'Fresher' },
{ Name: 'Laura', contact:'(206) 555-1189', id: '9', image: 'https://ej2.syncfusion.com/demos/src/grid/images/8.png', category: 'Experience' },
];
public fields: Object = { text: 'Name', groupBy: 'category' };
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { ListViewModule } from '@syncfusion/ej2-angular-lists';
/**
* Module
*/
@NgModule({
imports: [
BrowserModule,
ListViewModule
],
declarations: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule { }
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { AppModule } from './app.module';
enableProdMode();
platformBrowserDynamic().bootstrapModule(AppModule);
You can customize the ListView using the template property. Refer to the following steps to customize ListView as mobile contact view with our ej2-avatar
.
let data: any = [
{
text: "Jenifer",
contact: "(206) 555-985774",
id: "1",
avatar: "",
pic: "pic01"
},
{ text: "Amenda", contact: "(206) 555-3412", id: "2", avatar: "A", pic: "" },
];
avatar
classes in ListView template to customize contact icon. In the following codes, medium size avatar has been set using the class name e-avatar e-avatar-circle
from data source.{% raw %}
<ng-template #template let-data="">
<div class="e-list-wrapper e-list-multi-line e-list-avatar">
<span class="e-avatar e-avatar-circle" *ngIf="data.avatar !== ''">{{data.avatar}}</span>
<span class="{{data.pic}} e-avatar e-avatar-circle" *ngIf="data.pic !== '' "> </span>
<span class="e-list-item-header">{{data.text}}</span>
<span class="e-list-content">{{data.contact}}</span>
</div>
</ng-template>
{% endraw %}
Avatars can be set in different sizes in avatar classes. To know more about avatar classes, refer to Avatar.
sortOder
property of ListView.showHeader
property, and set the headerTitle
as Contacts
.import { Component } from '@angular/core';
@Component({
selector: 'my-app',
template: `
<div id="sample">
<ejs-listview id='List' [dataSource]='data' headerTitle='Contacts' cssClass='e-list-template' [showHeader]='true' sortOrder='Ascending'>
<ng-template #template let-data="">
<div class="e-list-wrapper e-list-multi-line e-list-avatar">
<span class="e-avatar e-avatar-circle" *ngIf="data.avatar !== ''">{{data.avatar}}</span>
<span class="{{data.pic}} e-avatar e-avatar-circle" *ngIf="data.pic !== '' "> </span>
<span class="e-list-item-header">{{data.text}}</span>
<span class="e-list-content">{{data.contact}}</span>
</div>
</ng-template>
</ejs-listview>
</div>
`
})
export class AppComponent {
// Listview datasource with avatar and image source fields
public data: { [key: string]: Object; }[] = [
{
text: "Jenifer",
contact: "(206) 555-985774",
id: "1",
avatar: "",
pic: "pic01"
},
{ text: "Amenda", contact: "(206) 555-3412", id: "2", avatar: "A", pic: "" },
{
text: "Isabella",
contact: "(206) 555-8122",
id: "4",
avatar: "",
pic: "pic02"
},
{
text: "William ",
contact: "(206) 555-9482",
id: "5",
avatar: "W",
pic: ""
},
{
text: "Jacob",
contact: "(71) 555-4848",
id: "6",
avatar: "",
pic: "pic04"
},
{ text: "Matthew", contact: "(71) 555-7773", id: "7", avatar: "M", pic: "" },
{
text: "Oliver",
contact: "(71) 555-5598",
id: "8",
avatar: "",
pic: "pic03"
},
{
text: "Charlotte",
contact: "(206) 555-1189",
id: "9",
avatar: "C",
pic: ""
}
];
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { ListViewModule } from '@syncfusion/ej2-angular-lists';
/**
* Module
*/
@NgModule({
imports: [
BrowserModule,
ListViewModule
],
declarations: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule { }
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { AppModule } from './app.module';
enableProdMode();
platformBrowserDynamic().bootstrapModule(AppModule);
The filtered data can be displayed in the ListView component depending upon on user inputs using the DataManager
. Refer to the following steps to render the ListView with filtered data.
dataSource
, and set the sortOrder
property.keyup
event for textbox to perform filtering operation. To filter list data, pass the list data source to the DataManager
, manipulate the data using the executeLocal
method, and then update filtered data as ListView dataSource.import { Component, ViewChild } from "@angular/core";
import { enableRipple } from "@syncfusion/ej2-base";
import { DataManager, Query, ODataV4Adaptor } from "@syncfusion/ej2-data";
import { ListViewComponent } from '@syncfusion/ej2-angular-lists';
enableRipple(true);
@Component({
selector: 'my-app',
template: `<div id="sample">
<input #textbox class="e-input" type="text" id="textbox" placeholder="Filter" title="Type in a name" (keyup)=onkeyup($event) />
<ejs-listview #list id='list' [dataSource]='listData' [fields]='fields' [sortOrder]='Ascending'></ejs-listview>
</div>`,
styles: [`
#list {
box-shadow: 0 1px 4px #ddd;
border-bottom: 1px solid #ddd;
}
#sample {
height: 220px;
margin: 0 auto;
display: table;
}
`]
})
export class AppComponent {
public listData: Object = [
{ text: "Hennessey Venom", id: "list-01" },
{ text: "Bugatti Chiron", id: "list-02" },
{ text: "Bugatti Veyron Super Sport", id: "list-03" },
{ text: "SSC Ultimate Aero", id: "list-04" },
{ text: "Koenigsegg CCR", id: "list-05" },
{ text: "McLaren F1", id: "list-06" }
];
public fields: Object = { text: "text", id: "id" };
@ViewChild('list')
listObj: ListViewComponent;
@ViewChild('textbox')textboxEle: any;
onkeyup(event: any){
let value = this.textboxEle.nativeElement.value;
let data = new DataManager(this.listData).executeLocal(new Query().where("text", "startswith", value, true));
if (!value) {
(this.listObj.dataSource as any) = (this.listData as Object[]).slice();
} else {
this.listObj.dataSource = data as { [key: string]: Object }[];
}
this.listObj.dataBind();
}
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { ListViewModule } from '@syncfusion/ej2-angular-lists';
/**
* Module
*/
@NgModule({
imports: [
BrowserModule,
ListViewModule
],
declarations: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule { }
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { AppModule } from './app.module';
enableProdMode();
platformBrowserDynamic().bootstrapModule(AppModule);
In this demo, data has been filtered with starting character of the list items. You can also filter list items with ending character by passing the
endswith
in where clause instead ofstartswith
.
The ListView component triggers events based on its actions. The events can be used as extension points to perform custom operations. Refer to the following steps to trace the ListView events:
actionBegin
, actionComplete
, and select
events.actionBegin
, actionComplete
, and select events.actionBegin
and actionComplete
events, and they will be displayed in the event trace panel when the ListView action starts and the dataSource bound successfully.SelectEventArgs
in the select event, and display the selected list item text in the event trace panel while selecting list items.import { Component, ViewChild, ViewEncapsulation } from "@angular/core";
import { SelectEventArgs } from "@syncfusion/ej2-lists";
@Component({
selector: 'my-app',
template: `<div id="sample">
<div class="content-wrapper">
<ejs-listview id='listview-def' [dataSource]='listData' [width]='250' (select)='onSelect($event)' (actionBegin)='onActionBegin($event)' (actionComplete)='onActionComplete($event)'></ejs-listview>
</div>
<div id="list_event">
<h4><b>Event Trace</b></h4>
<div id="evt">
<div class="eventarea" style="height:273px;overflow: auto">
<span #EventLog class="EventLog" id="EventLog" style="word-break: normal;"></span>
</div>
<div class="evtbtn">
<input ejs-button id="clear" type="button" value="Clear" (click)='onclick($event)'>
</div>
</div>
</div>
</div>`,
styles: [`
#EventLog b {
color: #388e3c;
}
#listview-def {
border: 1px solid #dcdcdc;
}
.content-wrapper {
padding-left: 40px;
padding-top: 36px;
}
.evtbtn {
margin-top: 40px;
margin-left: 70px;
}
/* csslint ignore:start */
hr {
margin-top: 6px !important;
margin-bottom: 6px !important;
}
/* csslint ignore:end */
#evt {
border: 1px solid #dcdcdc;
padding: 10px;
min-width: 10px;
}
#sample {
display: inline-flex;
}
.eventarea {
min-width: 250px;
}
#list_event {
margin-top: -25px;
padding-left:40px;
min-width: 200px;
}
`],
encapsulation: ViewEncapsulation.None
})
export class AppComponent {
@ViewChild('EventLog') EventLogEle:any;
public listData: Object = [
{ text: "Hennessey Venom", id: "list-01" },
{ text: "Bugatti Chiron", id: "list-02" },
{ text: "Bugatti Veyron Super Sport", id: "list-03" },
{ text: "SSC Ultimate Aero", id: "list-04" },
{ text: "Koenigsegg CCR", id: "list-05" },
{ text: "McLaren F1", id: "list-06" },
{ text: "Aston Martin One- 77", id: "list-07" },
{ text: "Jaguar XJ220", id: "list-08" },
{ text: "McLaren P1", id: "list-09" },
{ text: "Ferrari LaFerrari", id: "list-10" }
];
onclick(event: any){
this.EventLogEle.nativeElement.innerHTML = "";
}
onSelect(args: SelectEventArgs){
this.appendElement(args.text + "<b> is selected</b><hr>");
}
onActionBegin(){
this.appendElement("<b>actionBegin </b> event is triggered<hr>");
}
onActionComplete(){
this.appendElement("<b>actionComplete</b> is triggered <hr>");
}
appendElement(html: string): void {
let span: HTMLElement = document.createElement("span");
span.innerHTML = html;
let log: HTMLElement = this.EventLogEle.nativeElement;
log.insertBefore(span, log.firstChild);
}
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { ListViewModule } from '@syncfusion/ej2-angular-lists';
/**
* Module
*/
@NgModule({
imports: [
BrowserModule,
ListViewModule
],
declarations: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule { }
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { AppModule } from './app.module';
enableProdMode();
platformBrowserDynamic().bootstrapModule(AppModule);
The features of the ListView component such as remote data-binding take more time to fetch data from corresponding dataSource/remote URL. In this case, you can use EJ2 Spinner to enhance the appearance of the UI. This section explains how to load a spinner component to groom the appearance.
Refer to the following code sample to render the spinner component.
createSpinner({
target: this.spinnerEle.nativeElement
});
showSpinner(this.spinnerEle.nativeElement);
Refer to the following code sample to render the ListView component.
let listviewInstance: ListView = new ListView({
//Bind the DataManager instance to the dataSource property
dataSource= new DataManager({
url: '//js.syncfusion.com/ejServices/Wcf/Northwind.svc/',
crossDomain: true
}),
//Bind the Query instance to the query property
query= new Query().from('Products').select('ProductID,ProductName').take(10),
//Map the appropriate columns to the fields property
fields= { id: 'ProductID', text: 'ProductName' },
});
//Render the initialized ListView
listviewInstance.appendTo("#element");
Here, the data is fetched from Northwind
Service URL; it takes a few seconds to load the data. To enhance the UI, the spinner component has been rendered initially. After the data is loaded from remote URL, the spinner component will be hidden in ListView actionComplete event.
import { Component, ViewChild, AfterViewInit, ViewEncapsulation } from "@angular/core";
import { DataManager, Query, ODataV4Adaptor } from '@syncfusion/ej2-data';
import { createSpinner, showSpinner, setSpinner } from '@syncfusion/ej2-angular-popups';
import { ListViewComponent } from '@syncfusion/ej2-angular-lists';
@Component({
selector: 'my-app',
template: `
<ejs-listview id='element' #list [dataSource]='dataSource' [width]='300' [query]='query' [fields]='fields' [showHeader]='true' [headerTitle]='headertitle' (actionComplete)='onActionComplete($event)' >
</ejs-listview>
<div #spinner id="spinner" ></div>
`,
styles: [`
#element {
display: block;
max-width: 400px;
min-height: 200px;
margin: auto;
border: 1px solid #dddddd;
border-radius: 3px;
}
`],
encapsulation: ViewEncapsulation.None
})
export class AppComponent {
@ViewChild('spinner') spinnerEle:any;
public dataSource= new DataManager({
url: 'http://js.syncfusion.com/ejServices/Wcf/Northwind.svc/',
crossDomain: true
})
public query = new Query().from('Products').select('ProductID,ProductName').take(10);
public fields: Object = { id: 'ProductID', text: 'ProductName' };
public headertitle = 'Product Name';
AfterViewInit(){
createSpinner({
target: this.spinnerEle.nativeElement
});
showSpinner(this.spinnerEle.nativeElement);
}
onActionComplete(){
this.spinnerEle.nativeElement.style.display = "none";
}
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { ListViewModule } from '@syncfusion/ej2-angular-lists';
/**
* Module
*/
@NgModule({
imports: [
BrowserModule,
ListViewModule
],
declarations: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule { }
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { AppModule } from './app.module';
enableProdMode();
platformBrowserDynamic().bootstrapModule(AppModule);
You can add or remove list items from the ListView component using the
addItem
and
removeItem
methods.
Refer to the following steps to add or remove a list item.
addItem
method to add a
new list item on clicking the Add Item button.removeItem
method.import { Component, ViewChild } from '@angular/core';
import { ListViewComponent } from '@syncfusion/ej2-angular-lists';
@Component({
selector: 'my-app',
template: `<ejs-listview #list id='sample-list' [dataSource]='data' [fields]='fields' (actionComplete)='onComplete()'>
<ng-template #template let-data="">
<div class='text-content'> {{data.text}} <span class = 'delete-icon'></span> </div>
</ng-template>
</ejs-listview>
<button ejs-button id="btn" (click)="addItem()">Add Item</button>`,
})
export class AppComponent {
@ViewChild('list')
listviewInstance: ListViewComponent;
//define the array of string
public data: Object[] = [{ text: "Hennessey Venom", id: "1", icon: "delete-icon" },
{ text: "Bugatti Chiron", id: "2", icon: "delete-icon" },
{ text: "Bugatti Veyron Super Sport", id: "3", icon: "delete-icon" },
{ text: "Aston Martin One- 77", id: "4", icon: "delete-icon" },
{ text: "Jaguar XJ220", id: "list-5", icon: "delete-icon" },
{ text: "McLaren P1", id: "6", icon: "delete-icon" }];
public fields: Object = {text: "text", iconCss: "icon" };
deleteItem(args:any) {
args.stopPropagation();
let liItem = args.target.parentElement.parentElement;
this.listviewInstance.removeItem(liItem);
this.onComplete();
}
onComplete() {
let iconEle = document.getElementsByClassName("delete-icon");
//Event handler to bind the click event for delete icon
Array.from(iconEle).forEach((element) => {
element.addEventListener("click", this.deleteItem.bind(this));
});
}
addItem(){
let data = {
text: "Koenigsegg - " + (Math.random() * 1000).toFixed(0),
id: (Math.random() * 1000).toFixed(0).toString(),
icon: "delete-icon"
};
this.listviewInstance.addItem([data]);
}
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { ListViewModule } from '@syncfusion/ej2-angular-lists';
import { ButtonModule } from '@syncfusion/ej2-angular-buttons';
/**
* Module
*/
@NgModule({
imports: [
BrowserModule,
ListViewModule, ButtonModule
],
declarations: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule { }
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { AppModule } from './app.module';
enableProdMode();
platformBrowserDynamic().bootstrapModule(AppModule);
The dual list contains two ListView. This allows you to move list items from one list to another using the client-side events. This section explains how to integrate the ListView component to achieve dual list.
Here, two ListView components have been used to display the list items. An ej2-button is used to transfer data between the ListView, and a textbox is used to achieve the UI of filtering support.
The dual list supports:
In the ListView component, sorting is enabled using the sortOrder property, and the select event is triggered while selecting an item. Here, the select event is triggered to enable and disable button states.
concat
with the second ListView. This button is enabled only when the data source
of the first ListView is not empty.dataManager
has been
used to fetch data from the data source and display in ListView.import { Component, ViewChild } from "@angular/core";
import { enableRipple } from "@syncfusion/ej2-base";
import { DataManager, Query, ODataV4Adaptor } from "@syncfusion/ej2-data";
import { ListViewComponent } from '@syncfusion/ej2-angular-lists';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
enableRipple(true);
@Component({
selector: 'my-app',
template: `<div id="text1">
<input #textbox class="e-input" type="text" id="firstInput" placeholder="Filter" title="Type in a name" (keyup)="onFirstKeyUp($event)" />
</div>
<ejs-listview #list1 id='list-1' [dataSource]='firstListData' [fields]='fields' [sortOrder]='Ascending' (select)="onFirstListSelect()"></ejs-listview>
<div id="btn">
<button ejs-button #btn1 id="firstBtn" (click)="firstbtnclick()"> >> </button>
<button ejs-button #btn2 id="secondBtn" [disabled]=true (click)="secondbtnclick()"> > </button>
<button ejs-button #btn3 id="thirdBtn" [disabled]=true (click)="thirdbtnclick()"> < </button>
<button ejs-button #btn4 id="fourthBtn" (click)="fourthbtnclick()"> << </button>
</div>
<div id="text2">
<input #text class="e-input" type="text" id="secondInput" placeholder="Filter" title="Type in a name" (keyup)="onSecondKeyUp($event)" />
</div>
<ejs-listview #list2 id='list-2' [dataSource]='secondListData' [fields]='fields' [sortOrder]='Ascending' (select)="onSecondListSelect()"></ejs-listview>
`,
})
export class AppComponent {
public fields: Object;
public firstListData: any; secondListData: any;
constructor(){
this.firstListData = [
{ text: "Hennessey Venom", id: "list-01" },
{ text: "Bugatti Chiron", id: "list-02" },
{ text: "Bugatti Veyron Super Sport", id: "list-03" },
{ text: "SSC Ultimate Aero", id: "list-04" },
{ text: "Koenigsegg CCR", id: "list-05" },
{ text: "McLaren F1", id: "list-06" }
];
this.secondListData = [
{ text: 'Aston Martin One- 77', id: 'list-07' },
{ text: 'Jaguar XJ220', id: 'list-08' },
{ text: 'McLaren P1', id: 'list-09' },
{ text: 'Ferrari LaFerrari', id: 'list-10' },
];
this.fields = { text: "text", id: "id" };
}
@ViewChild('list1')firstListObj: ListViewComponent;
@ViewChild('list2')secondListObj: ListViewComponent;
@ViewChild('btn1')firstBtnObj: ButtonComponent;
@ViewChild('btn2')secondBtnObj: ButtonComponent;
@ViewChild('btn3')thirdBtnObj: ButtonComponent;
@ViewChild('btn4')fourthBtnObj: ButtonComponent;
@ViewChild('textbox')textboxEle: any;
@ViewChild('text')textEle: any;
ngAfterViewInit(){
this.firstListData = (this.firstListObj.dataSource as { [key: string]: Object; }[]).slice();
this.secondListData = (this.secondListObj.dataSource as { [key: string]: Object; }[]).slice();
}
//Here, all list items are moved to the second list on clicking move all button
firstbtnclick() {
let e = this.firstListObj.getSelectedItems();
this.secondListObj.dataSource = Array.prototype.concat.call(this.firstListObj.dataSource, this.secondListObj.dataSource);
this.updateFirstListData();
this.firstListObj.removeMultipleItems((this.firstListObj as any).liCollection);
this.firstListData = this.firstListData.concat(this.firstListObj.dataSource);
this.secondListData = (this.secondListObj.dataSource as { [key: string]: Object; }[]).slice();
this.firstBtnObj.disabled = true;
this.onFirstKeyUp(e);
this.setButtonState();
}
//Here, the selected list items are moved to the second list on clicking move button
secondbtnclick() {
let e = this.firstListObj.getSelectedItems();
this.secondListObj.dataSource = Array.prototype.concat.call(this.secondListObj.dataSource, e.data);
(this.firstListObj as any).removeItem(e.item);
this.firstListData = this.firstListObj.dataSource;
(this.secondListData = this.secondListObj.dataSource as { [key: string]: Object; }[]).slice();
this.onFirstKeyUp(e);
this.secondBtnObj.disabled = true;
this.setButtonState();
}
//Here, the selected list items are moved to the first list on clicking move button
thirdbtnclick () {
let e = this.secondListObj.getSelectedItems();
this.firstListObj.dataSource = Array.prototype.concat.call(this.firstListObj.dataSource, e.data);
(this.secondListObj as any).removeItem(e.item);
this.secondListData = this.secondListObj.dataSource;
this.firstListData = (this.firstListObj.dataSource as { [key: string]: Object; }[]).slice();
this.onSecondKeyUp(e);
this.thirdBtnObj.disabled = true;
this.setButtonState();
}
//Here, all list items are moved to the first list on clicking move all button
fourthbtnclick() {
let e = this.secondListObj.getSelectedItems();
this.firstListObj.dataSource = Array.prototype.concat.call(this.firstListObj.dataSource, this.secondListObj.dataSource);
this.updateSecondListData();
this.secondListObj.removeMultipleItems((this.secondListObj as any).liCollection);
this.secondListData = this.secondListData.concat(this.secondListObj.dataSource);
this.firstListData = (this.firstListObj.dataSource as { [key: string]: Object; }[]).slice();
this.onSecondKeyUp(e);
this.setButtonState();
}
//Here, the ListView data source is updated to the first list
updateFirstListData() {
Array.prototype.forEach.call((this.firstListObj as any).liCollection, (list: any) => {
this.firstListData.forEach((data: any, index: any) => {
if (list.innerText.trim() === data.text) {
delete this.firstListData[index];
}
});
});
this.textboxEle.nativeElement.value= '';
let ds: any = [];
this.firstListData.forEach((data: any) => {
ds.push(data);
})
this.firstListData = ds;
}
//Here, the ListView dataSource is updated for the second list
updateSecondListData() {
Array.prototype.forEach.call((this.secondListObj as any).liCollection, (list: any) => {
this.secondListData.forEach((data: any, index: any) => {
if (list.innerText.trim() === data.text) {
delete this.secondListData[index];
}
});
});
this.textEle.nativeElement.value = '';
let ds: any = [];
this.secondListData.forEach((data: any) => {
ds.push(data);
})
this.secondListData = ds;
}
onFirstListSelect() {
this.secondBtnObj.disabled = false;
}
onSecondListSelect() {
this.thirdBtnObj.disabled = false;
}
//Here, filtering is handled using the dataManager for the first list
onFirstKeyUp(e: any) {
let value = this.textboxEle.nativeElement.value;
let data = new DataManager(this.firstListData).executeLocal(new Query().where('text', 'startswith', value, true));
if (!value) {
this.firstListObj.dataSource = this.firstListData.slice();
} else {
(this.firstListObj.dataSource as any) = data;
}
}
//Here, filtering is handled using the dataManager for the second list
onSecondKeyUp(e:any) {
let value =this.textEle.nativeElement.value;
let data = new DataManager(this.secondListData).executeLocal(new Query().where('text', 'startswith', value, true));
if (!value) {
this.secondListObj.dataSource = this.secondListData.slice();
} else {
this.secondListObj.dataSource = data as { [key: string]: Object }[];
}
}
//Here, the state of the button is changed
setButtonState() {
if ((this.firstListObj.dataSource as any).length) {
this.firstBtnObj.disabled = false;
} else {
this.firstBtnObj.disabled = true;
this.secondBtnObj.disabled = true;
}
if ((this.secondListObj.dataSource as any).length) {
this.fourthBtnObj.disabled = false;
} else {
this.fourthBtnObj.disabled = true;
this.thirdBtnObj.disabled = true;
}
}
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { ListViewModule } from '@syncfusion/ej2-angular-lists';
import { ButtonModule } from '@syncfusion/ej2-angular-buttons';
/**
* Module
*/
@NgModule({
imports: [
BrowserModule,
ListViewModule, ButtonModule
],
declarations: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule { }
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { AppModule } from './app.module';
enableProdMode();
platformBrowserDynamic().bootstrapModule(AppModule);
The checkbox of the any list item can be hidden by using
htmlAttributes
of
fields
object. With
the help of htmlAttributes
we can add unique class to each list item that will be rendered from the data source, from
the CSS class we can hide the checkbox of the list item.
In this sample, we had hidden the multiple leaf node of nested list. The e-checkbox-hidden
class has been added in the data
source where the checkbox needs to be hidden. Refer the below snippet for simple data source.
{
'text': 'New York',
'id': '3002',
'category': 'USA',
'htmlAttributes': { 'class': 'e-file e-checkbox-hidden' }
}
Even though we have hidden the checkbox the functionality will be same for the list item which might affect the
getSelectedItems
method. So, to counteract that we will follow certain logic in the select
event. The Logic here is to
remove the e-active
class from the other checkbox hidden list item which will be added when we select on that item and
retain e-active
on currently selected item.
In this process we will exclude the visible checkbox list items and only consider the hidden checkbox items.
import { Component, ViewChild } from "@angular/core";
import { ListViewComponent } from '@syncfusion/ej2-angular-lists';
@Component({
selector: 'my-app',
template: `
<div id="sample">
<ejs-listview #list id='folderCheckbox' [dataSource]='dataSource' [fields]='fields' [sortOrder]='Ascending' headerTitle='Mixed Leaf Checkbox Hidden List' [showHeader]=true [showCheckBox]=true (select)="onSelect($event)"></ejs-listview>
</div>
`,
})
export class AppComponent {
public dataSource: Object = [
{
'text': 'Asia',
'id': '01',
'category': 'Continent',
'child': [{
'text': 'India',
'id': '1',
'category': 'Asia',
'child': [{
'text': 'Delhi',
'id': '1001',
'category': 'India',
'htmlAttributes': { 'class': 'e-file e-checkbox-hidden' },
},
{
'text': 'Kashmir',
'id': '1002',
'category': 'India',
'htmlAttributes': { 'class': 'e-file e-checkbox-hidden' },
},
{
'text': 'Goa',
'id': '1003',
'category': 'India',
'htmlAttributes': { 'class': 'e-file' },
},
]
},
{
'text': 'China',
'id': '2',
'category': 'Asia',
'child': [{
'text': 'Zhejiang',
'id': '2001',
'category': 'China',
'htmlAttributes': { 'class': 'e-file' },
},
{
'text': 'Hunan',
'id': '2002',
'category': 'China',
'htmlAttributes': { 'class': 'e-file e-checkbox-hidden' },
},
{
'text': 'Shandong',
'id': '2003',
'category': 'China',
'htmlAttributes': { 'class': 'e-file' },
}]
}]
},
{
'text': 'North America',
'id': '02',
'category': 'Continent',
'child': [{
'text': 'USA',
'id': '3',
'category': 'North America',
'child': [{
'text': 'California',
'id': '3001',
'category': 'USA',
'htmlAttributes': { 'class': 'e-file e-checkbox-hidden' },
},
{
'text': 'New York',
'id': '3002',
'category': 'USA',
'htmlAttributes': { 'class': 'e-file e-checkbox-hidden' },
},
{
'text': 'Florida',
'id': '3003',
'category': 'USA',
'htmlAttributes': { 'class': 'e-file' },
}]
},
{
'text': 'Canada',
'id': '4',
'category': 'North America',
'child': [{
'text': 'Ontario',
'id': '4001',
'category': 'Canada',
'htmlAttributes': { 'class': 'e-file e-checkbox-hidden' },
},
{
'text': 'Alberta',
'id': '4002',
'category': 'Canada',
'htmlAttributes': { 'class': 'e-file' },
},
{
'text': 'Manitoba',
'id': '4003',
'category': 'Canada',
'htmlAttributes': { 'class': 'e-file' },
}]
}]
},
{
'text': 'Europe',
'id': '03',
'category': 'Continent',
'child': [{
'text': 'Germany',
'id': '5',
'category': 'Europe',
'child': [{
'text': 'Berlin',
'id': '5001',
'category': 'Germany',
'htmlAttributes': { 'class': 'e-file e-checkbox-hidden' },
},
{
'text': 'Bavaria',
'id': '5002',
'category': 'Germany',
'htmlAttributes': { 'class': 'e-file' },
},
{
'text': 'Hesse',
'id': '5003',
'category': 'Germany',
'htmlAttributes': { 'class': 'e-file e-checkbox-hidden' },
}]
}, {
'text': 'France',
'id': '6',
'category': 'Europe',
'child': [{
'text': 'Paris',
'id': '6001',
'category': 'France',
'htmlAttributes': { 'class': 'e-file' },
},
{
'text': 'Lyon',
'id': '6002',
'category': 'France',
'htmlAttributes': { 'class': 'e-file e-checkbox-hidden' },
},
{
'text': 'Marseille',
'id': '6003',
'category': 'France',
'htmlAttributes': { 'class': 'e-file' },
}]
}]
},
{
'text': 'Australia',
'id': '04',
'category': 'Continent',
'child': [{
'text': 'Australia',
'id': '7',
'category': 'Australia',
'child': [{
'text': 'Sydney',
'id': '7001',
'category': 'Australia',
'htmlAttributes': { 'class': 'e-file e-checkbox-hidden' },
},
{
'text': 'Melbourne',
'id': '7002',
'category': 'Australia',
'htmlAttributes': { 'class': 'e-file' },
},
{
'text': 'Brisbane',
'id': '7003',
'category': 'Australia',
'htmlAttributes': { 'class': 'e-file' },
}]
}, {
'text': 'New Zealand',
'id': '8',
'category': 'Australia',
'child': [{
'text': 'Milford Sound',
'id': '8001',
'category': 'New Zealand',
'htmlAttributes': { 'class': 'e-file' },
},
{
'text': 'Tongariro National Park',
'id': '8002',
'category': 'New Zealand',
'htmlAttributes': { 'class': 'e-file' },
},
{
'text': 'Fiordland National Park',
'id': '8003',
'category': 'New Zealand',
'htmlAttributes': { 'class': 'e-file e-checkbox-hidden' },
}]
}]
},
{
'text': 'Africa',
'id': '05',
'category': 'Continent',
'child': [{
'text': 'Morocco',
'id': '9',
'category': 'Africa',
'child': [{
'text': 'Rabat',
'id': '9001',
'category': 'Morocco',
'htmlAttributes': { 'class': 'e-file e-checkbox-hidden' },
},
{
'text': 'Toubkal',
'id': '9002',
'category': 'Morocco',
'htmlAttributes': { 'class': 'e-file' },
},
{
'text': 'Todgha Gorge',
'id': '9003',
'category': 'Morocco',
'htmlAttributes': { 'class': 'e-file e-checkbox-hidden' },
}]
}, {
'text': 'South Africa',
'id': '10',
'category': 'Africa',
'child': [{
'text': 'Cape Town',
'id': '10001',
'category': 'South Africa',
'htmlAttributes': { 'class': 'e-file e-checkbox-hidden' },
},
{
'text': 'Pretoria',
'id': '10002',
'category': 'South Africa',
'htmlAttributes': { 'class': 'e-file e-checkbox-hidden' },
},
{
'text': 'Bloemfontein',
'id': '10003',
'category': 'South Africa',
'htmlAttributes': { 'class': 'e-file' },
}]
}]
}
];
public fields = { tooltip: 'text' };
@ViewChild('list')listviewInstance: ListViewComponent;
onSelect(args: any){
let normalElements: HTMLElement[] = Array.prototype.slice.call((this.listviewInstance as any).curUL.getElementsByClassName('e-checkbox-hidden'));
// Looping through all the selected element and removing e-active class
// to avoid behaviour interference with getSelectedItems method
normalElements.forEach((element) => {
element.classList.remove('e-active');
});
// Finally adding e-active class to currently selected item except checkbox item.
// because if it is checkbox item their actions will taken care from the source side itself.
if (args.item.classList.contains('e-checkbox-hidden')) {
args.item.classList.add('e-active');
}
}
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { ListViewModule } from '@syncfusion/ej2-angular-lists';
/**
* Module
*/
@NgModule({
imports: [
BrowserModule,
ListViewModule
],
declarations: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule { }
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { AppModule } from './app.module';
enableProdMode();
platformBrowserDynamic().bootstrapModule(AppModule);
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.
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);
}
created
event.//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();
}
}
//Method to remove the list item
removeTag() {
this.parentNode.parentNode.remove();
}
import { Component, ViewChild } from '@angular/core';
import { ListViewComponent } from '@syncfusion/ej2-angular-lists';
import { DialogComponent } from '@syncfusion/ej2-angular-popups';
@Component({
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">{{data.Name}} </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></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.Brooke' [fields]='fields' (select)='addTag($event)'></ejs-listview>
</ng-template>
</ejs-dialog>
</div>`
})
export class AppComponent {
parentNode:any;
@ViewChild('list') listviewInstance: ListViewComponent;
@ViewChild('List') listObj: ListViewComponent;
@ViewChild('ejDialog') dialog: DialogComponent;
//define the array of string
public data: Object[] = [{ "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 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 - } 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 };
ngAfterViewChecked(){
setTimeout(()=>{
this.position = { X: document.querySelector('.e-add-icon').getBoundingClientRect().left + 50, Y: document.querySelector('.e-add-icon').getBoundingClientRect().top - 5 };
},1000);
}
onClick(e: any){
this.renderDialog(e.currentTarget.id);
}
renderDialog(id: any) {
if (document.getElementsByClassName('e-popup-open').length != 0) {
this.dialog.hide();
}
else {
this.listObj.dataSource = this.datasource[id];
this.listObj.dataBind();
this.dialog.show();
}
}
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 = 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);
}
removeTag() {
this.parentNode.parentNode.remove();
}
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { ListViewModule } from '@syncfusion/ej2-angular-lists';
import { DialogModule } from '@syncfusion/ej2-angular-popups';
import { ButtonModule } from '@syncfusion/ej2-angular-buttons';
/**
* Module
*/
@NgModule({
imports: [
BrowserModule,
ListViewModule,
DialogModule,
ButtonModule
],
declarations: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule { }
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { AppModule } from './app.module';
enableProdMode();
platformBrowserDynamic().bootstrapModule(AppModule);
In Listview, list items can be rendered in grid layout with following data manipulations.
In this section, we will discuss about rendering of list items in grid layout.
#element .e-list-item {
height: 100px;
width: 100px;
float: left;
}
In the below sample, we have rendered List items in grid layout.
import { Component, ViewChild } from '@angular/core';
@Component({
selector: 'my-app',
template: `
<ejs-listview id='element' [dataSource]='data'>
<ng-template #template let-data="">
<img id="listImage" src="./apple.png" alt="apple" />
</ng-template>
</ejs-listview>
`,
})
export class AppComponent {
public data = [1, 2, 3, 4, 5, 6, 7, 8, 9];
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { ListViewModule } from '@syncfusion/ej2-angular-lists';
/**
* Module
*/
@NgModule({
imports: [
BrowserModule,
ListViewModule
],
declarations: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule { }
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { AppModule } from './app.module';
enableProdMode();
platformBrowserDynamic().bootstrapModule(AppModule);
In this section, we will discuss about ListView data manipulations.
We can add list item using addItem
API. This will accept array of data as argument.
this.$refs.listViewInstance.addItem([{text: 'Apricot', id: '32'}]);
In the below sample, you can add new fruit item by clicking add button which will open dialog box with fruit name and image URL text box. After entering the item details, click the add button. This will add your new fruit item.
We can remove list item using removeItem
API. This will accept fields with id
or list item element as argument.
this.$refs.listViewInstance.removeItem({id: '32'});
In the below sample, you can remove fruit by hovering the fruit item which will show delete button and click that delete button to delete that fruit from your list.
Listview can be sorted either in Ascending or Descending order. To enable sorting in your ListView, set sortOrder
as Ascending
or Descending
.
<ejs-listview sortOrder='Ascending'></ejs-listview>
We can also set sorting after component initialization.
this.listViewInstance.sortOrder = 'Ascending'
In the below sample, we have sorted fruits in Ascending
order. To sort it in descending, click on sort order icon and vice versa.
Listview data can be filtered with the help of dataManager
. After filtering the data, update ListView dataSource
with filtered data.
let value = this.textboxEle.nativeElement.value; //input text box value
let filteredData = new DataManager(this.listdata).executeLocal(
new Query().where("text", "startswith", value, true)
);
listViewInstance.dataSource = filteredData;
In the below sample, we can filter fruit items with the help of search text box. This will filter fruit items based on your input. Here we used startswith
of input text to filter data in DataManager.
import { Component, ViewChild, ElementRef } from '@angular/core';
import { closest, enableRipple } from '@syncfusion/ej2-base';
import { DataManager, Query } from "@syncfusion/ej2-data";
enableRipple(true);
@Component({
selector: 'my-app',
template: `
<div id="sample">
<div class="headerContainer">
<div class="e-input-group">
<input id="search" #searchEle class="e-input" type="text" placeholder="Search fruits" (keyup)='onKeyUp($event)'/>
<span class="e-input-group-icon e-input-search"></span>
</div>
<button ejs-button id="sort" class="e-control e-btn e-small e-round e-primary e-icon-btn" (click)='sortItems($event)' title="Sort fruits" data-ripple="true">
<span class="e-btn-icon e-icons e-sort-icon-ascending"></span>
</button>
<button ejs-button id="add" class="e-control e-btn e-small e-round e-primary e-icon-btn" (click)='addItem($event)' title="Add fruit" data-ripple="true">
<span class="e-btn-icon e-icons e-add-icon"></span>
</button>
<ejs-dialog id="dialog" #dialogObj width='300px' [visible]='false' header='Add Fruit' showCloseIcon='true' [buttons]='addButtons'>
<ng-template #content let-data="">
<div id="listDialog"><div class="input_name"><label for="name">Fruit Name: </label><input id="name" class="e-input" type="text" placeholder="Enter fruit name"/></div><div><label for="imgurl">Fruit Image: </label><input id="imgurl" class="e-input" type="text" placeholder="Enter image url"/></div></div>
</ng-template>
</ejs-dialog>
</div>
<ejs-listview id='element' #listview [dataSource]='fruitsdata' sortOrder='Ascending' (actionComplete)='wireEvents()'>
<ng-template #template let-data="">
<div class="fruits"><div class="first"><img id="listImage" src={{data.imgUrl}} alt="fruit" /><button ejs-button class="delete e-control e-btn e-small e-round e-delete-btn e-primary e-icon-btn" data-ripple="true"><span class="e-btn-icon e-icons delete-icon"></span></button></div><div class="fruitName">{{data.text}}</div></div>
</ng-template>
</ejs-listview>
</div>
`,
})
export class AppComponent {
@ViewChild('listview') listViewInstance: any;
@ViewChild('dialogObj')dialogObj: any;
@ViewChild('searchEle')searchEle: any;
public fruitsdata = [
{ text: 'Date', id: '1', imgUrl: './dates.jpg' },
{ text: 'Fig', id: '2', imgUrl: './fig.jpg' },
{ text: 'Apple', id: '3', imgUrl: './apple.png' },
{ text: 'Apricot', id: '4', imgUrl: './apricot.jpg' },
{ text: 'Grape', id: '5', imgUrl: './grape.jpg' },
{ text: 'Strawberry', id: '6', imgUrl: './strawberry.jpg' },
{ text: 'Pineapple', id: '7', imgUrl: './pineapple.jpg' },
{ text: 'Melon', id: '8', imgUrl: './melon.jpg' },
{ text: 'Lemon', id: '9', imgUrl: './lemon.jpg' },
{ text: 'Cherry', id: '10', imgUrl: './cherry.jpg' },
];
public addButtons= [{
click: this.dlgButtonClick.bind(this), buttonModel: { content: 'Add', isPrimary: true }
}];
wireEvents() {
Array.prototype.forEach.call(document.getElementsByClassName('e-delete-btn'), (ele: any) => {
ele.addEventListener('click', this.onDeleteBtnClick.bind(this));
});
}
addItem() {
((document.getElementById("name")) as HTMLInputElement).value = "";
((document.getElementById("imgurl")) as HTMLInputElement).value = "";
this.dialogObj.show();
}
sortItems() {
let ele = document.getElementById("sort").firstElementChild;
let des = ele.classList.contains('e-sort-icon-descending') ? true : false;
if (des) {
ele.classList.remove('e-sort-icon-descending');
ele.classList.add('e-sort-icon-ascending');
this.listViewInstance.sortOrder = 'Ascending';
} else {
ele.classList.remove('e-sort-icon-ascending');
ele.classList.add('e-sort-icon-descending');
this.listViewInstance.sortOrder = 'Descending'
}
this.listViewInstance.dataBind();
this.wireEvents();
}
onKeyUp(e: any) {
let value = this.searchEle.nativeElement.value;
let data = new DataManager(this.fruitsdata).executeLocal(
new Query().where("text", "startswith", value, true)
);
if (!value) {
this.listViewInstance.dataSource = this.fruitsdata.slice();
} else {
this.listViewInstance.dataSource = data;
this.listViewInstance.dataBind();
}
}
onDeleteBtnClick(e: any) {
e.stopPropagation();
let li = closest(e.currentTarget, '.e-list-item');
let data = this.listViewInstance.findItem(li);
this.listViewInstance.removeItem(data);
new DataManager(this.fruitsdata).remove('id', { id: data.id });
}
dlgButtonClick() {
let name = ((document.getElementById("name")) as HTMLInputElement).value;
let url = ((document.getElementById("imgurl")) as HTMLInputElement).value;
let id = `${Math.random() * 10000}`;
this.listViewInstance.addItem([{ text: name, id: id, imgUrl: url }]);
this.fruitsdata.push({ text: name, id: id, imgUrl: url });
this.listViewInstance.element.querySelector('[data-uid="'+ id + '"]').getElementsByClassName('e-delete-btn')[0].addEventListener('click', this.onDeleteBtnClick.bind(this));
this.dialogObj.hide();
}
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { ListViewModule } from '@syncfusion/ej2-angular-lists';
import { DialogComponent } from '@syncfusion/ej2-angular-popups';
/**
* Module
*/
@NgModule({
imports: [
BrowserModule,
ListViewModule
],
declarations: [AppComponent,DialogComponent],
bootstrap: [AppComponent]
})
export class AppModule { }
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { AppModule } from './app.module';
enableProdMode();
platformBrowserDynamic().bootstrapModule(AppModule);
We can use anchor
tag along with href
attribute in our ListView template
property for navigation.
{% raw %}
<ng-template #template let-data="">
<a target='_blank' href="{{data.url}}">{{data.name}}</a>
</ng-template>
{% endraw %}
In the below sample, we have rendered ListView
with search engines URL.
import { Component, ViewChild } from '@angular/core';
@Component({
selector: 'my-app',
template: `
<div id="sample">
<ejs-listview id='List' [dataSource]='data' headerTitle='Search engines' showHeader='true'>
<ng-template #template let-data="">
<a target='_blank' href="{{data.url}}">{{data.name}}</a>
</ng-template>
</ejs-listview>
</div>
`,
})
export class AppComponent {
public data=[
{name: 'Google', url: 'https://www.google.com'},
{name: 'Bing', url: 'https://www.bing.com' },
{name: 'Yahoo', url: 'https://www.yahoo.com'},
{name: 'Ask.com', url: 'https://www.ask.com'},
{name: 'AOL.com', url: 'https://www.aol.com'},
];
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { ListViewModule } from '@syncfusion/ej2-angular-lists';
/**
* Module
*/
@NgModule({
imports: [
BrowserModule,
ListViewModule
],
declarations: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule { }
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { AppModule } from './app.module';
enableProdMode();
platformBrowserDynamic().bootstrapModule(AppModule);
We can set external HTML
page content as template
for our ListView
component by making use of AJAX
call.
let ajax = new Ajax('./template.html', 'GET', false);
ajax.onSuccess = (e)=>{
this.listtemplate = e;
};
ajax.send();
In the below sample, we have rendered smartphone settings template from external HTML
file.
import { Component, ViewChild } from '@angular/core';
import { Ajax } from '@syncfusion/ej2-base';
@Component({
selector: 'my-app',
template: `
<ejs-listview id='List' [dataSource]='data' showHeader='true' headerTitle='Settings' [template]="listtemplate">
</ejs-listview>
`
})
export class AppComponent {
public listtemplate: any;
public data = [
{ name: 'Network & Internet', id: '0', description: 'Wi-Fi, mobile, data usage, hotspot' },
{ name: 'Connected devices', id: '1', description: 'Bluetooth, cast, NFC' },
{ name: 'Battery', id: '2', description: '18% -4h 12m left' },
{ name: 'Display', id: '3', description: 'Wallpaper, sleep, font size' },
{ name: 'Sound', id: '4', description: 'Volume, vibration, Do Not Disturb' },
{ name: 'Storage', id: '5', description: '52% used - 15.48 GB free' }
];
ngOnInit(){
let ajax = new Ajax('./template.html', 'GET', false);
ajax.onSuccess = (e: any)=>{
this.listtemplate = e;
};
ajax.send();
}
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { ListViewModule } from '@syncfusion/ej2-angular-lists';
/**
* Module
*/
@NgModule({
imports: [
BrowserModule,
ListViewModule
],
declarations: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule { }
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { AppModule } from './app.module';
enableProdMode();
platformBrowserDynamic().bootstrapModule(AppModule);
In ListView component, we don’t have drag and drop support. But we can achieve this requirement using TreeView
component with ListView appearance.
Drag and Drop in TreeView component was enabled by setting allowDragAndDrop
to true
.
<ejs-treeview id='element' [fields]='fields' allowDragAndDrop='true'></ejs-treeview>
The TreeView component is used to represent hierarchical data in a tree like structure. So, list items in TreeView can be dropped to child of target element. we can prevent this behaviour by cancelling the nodeDragStop
and nodeDragging
events.
<ejs-treeview id='element' [fields]='fields' allowDragAndDrop='true' (nodeDragging)='onDragStop($event)' (nodeDragStop)='onDragStop($event)'></ejs-treeview>
fields= { dataSource: this.data, id: 'id', text: 'text' },
onDragStop(args) {
//Block the Child Drop operation in TreeView
let draggingItem = document.getElementsByClassName("e-drop-in");
if (draggingItem.length == 1) {
draggingItem[0].classList.add('e-no-drop');
args.cancel = true;
}
}
In the below sample, we have rendered draggable list items.
import { Component, ViewChild } from '@angular/core';
@Component({
selector: 'my-app',
template: `
<div id="sample">
<ejs-treeview id='element' [fields]='fields' allowDragAndDrop='true' (nodeDragging)='onDragStop($event)' (nodeDragStop)='onDragStop($event)'></ejs-treeview>
</div>
`,
})
export class AppComponent {
public data=[
{ text: 'Hennessey Venom', id: 'list-01' },
{ text: 'Bugatti Chiron', id: 'list-02' },
{ text: 'Bugatti Veyron Super Sport', id: 'list-03' },
{ text: 'SSC Ultimate Aero', id: 'list-04' },
{ text: 'Koenigsegg CCR', id: 'list-05' },
{ text: 'McLaren F1', id: 'list-06' },
{ text: 'Aston Martin One- 77', id: 'list-07' },
{ text: 'Jaguar XJ220', id: 'list-08' },
{ text: 'McLaren P1', id: 'list-09' },
{ text: 'Ferrari LaFerrari', id: 'list-10' },
];
public fields = { dataSource: this.data, id: 'id', text: 'text' };
onDragStop(args:any) {
//Block the Child Drop operation in TreeView
let draggingItem = document.getElementsByClassName("e-drop-in");
if (draggingItem.length == 1) {
draggingItem[0].classList.add('e-no-drop');
args.cancel = true;
}
}
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { TreeViewModule } from '@syncfusion/ej2-angular-navigations';
/**
* Module
*/
@NgModule({
imports: [
BrowserModule,
TreeViewModule
],
declarations: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule { }
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { AppModule } from './app.module';
enableProdMode();
platformBrowserDynamic().bootstrapModule(AppModule);
ListView can be customizable as chat window. To achieve that, use ListView template property and Avatar component.
Refer the below template code snippet for Template of chat window.
{% raw %}
<ng-template #template let-data="">
<div class="settings" *ngIf="data.chat!='receiver' then senderTemplate else receiverTemplate "></div>
<ng-template #senderTemplate>
<div id="content">
<div class="name">{{data.text}}</div>
<div id="info">{{data.contact}}</div>
</div>
<div id="image" *ngIf="data.avatar!=''"><span class="e-avatar img1 e-avatar-circle">{{data.avatar}}</span></div>
<div id="image" *ngIf="data.avatar==''"><span class="{{data.pic}} img1 e-avatar e-avatar-circle"> </span></div>
</ng-template>
<ng-template #receiverTemplate>
<div id="image2" *ngIf="data.avatar!=''"><span class="e-avatar img2 e-avatar-circle">{{data.avatar}}</span></div>
<div id="image2" *ngIf="data.avatar==''"><span class="{{data.pic}} img2 e-avatar e-avatar-circle"> </span></div>
<div id="content1">
<div class="name1">{{data.text}}</div>
<div id="info1">{{data.contact}}</div>
</div>
</ng-template>
</ng-template>
{% endraw %}
In ListView template, we have rendered the list items based on receiver and sender information from dataSource of listview.
public btnClick() {
let value = this.textboxEle.nativeElement.value;
this.listObj.addItem([{ text: "Amenda", contact: value, id: "2", avatar: "A", pic: "", chat: "receiver" }]);
this.textboxEle.nativeElement.value = "";
}
import { Component, ViewChild } from '@angular/core';
@Component({
selector: 'my-app',
template: `
<ejs-listview id='List' #list [dataSource]='data' headerTitle="Chat" showHeader="true" width="350px" [fields]='fields'>
<ng-template #template let-data="">
<div class="settings" *ngIf="data.chat!='receiver' then senderTemplate else receiverTemplate "></div>
<ng-template #senderTemplate>
<div id="content">
<div class="name">{{data.text}}</div>
<div id="info">{{data.contact}}</div>
</div>
<div id="image" *ngIf="data.avatar!=''"><span class="e-avatar img1 e-avatar-circle">{{data.avatar}}</span></div>
<div id="image" *ngIf="data.avatar==''"><span class="{{data.pic}} img1 e-avatar e-avatar-circle"> </span></div>
</ng-template>
<ng-template #receiverTemplate>
<div id="image2" *ngIf="data.avatar!=''"><span class="e-avatar img2 e-avatar-circle">{{data.avatar}}</span></div>
<div id="image2" *ngIf="data.avatar==''"><span class="{{data.pic}} img2 e-avatar e-avatar-circle"> </span></div>
<div id="content1">
<div class="name1">{{data.text}}</div>
<div id="info1">{{data.contact}}</div>
</div>
</ng-template>
</ng-template>
</ejs-listview>
<div style="width: 350px;margin: 0 auto;"><input #textbox id="name" style="width: 275px" class="e-input" type="text" placeholder="Type your message" />
<button ejs-button id="btn" style="float:right" (click)="btnClick()">Send</button> </div>
`,
})
export class AppComponent {
@ViewChild('list') listObj: any;
@ViewChild('textbox') textboxEle: any;
public data: 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: "pic02", 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"
},
];
public fields = { text: "Name" };
public btnClick() {
let value = this.textboxEle.nativeElement.value;
this.listObj.addItem([{ text: "Amenda", contact: value, id: "2", avatar: "A", pic: "", chat: "receiver" }]);
this.textboxEle.nativeElement.value = "";
}
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { ListViewModule } from '@syncfusion/ej2-angular-lists';
import { ButtonModule } from '@syncfusion/ej2-angular-buttons';
/**
* Module
*/
@NgModule({
imports: [
BrowserModule,
ListViewModule, ButtonModule
],
declarations: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule { }
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { AppModule } from './app.module';
enableProdMode();
platformBrowserDynamic().bootstrapModule(AppModule);