Manipulate ListView as grid layout in Angular ListView component
12 Sep 202521 minutes to read
The ListView component can display items in a grid layout with support for data manipulations such as adding, removing, sorting, and filtering items.
Grid Layout
To render list items in a grid layout:
- Initialize the ListView with a dataSource
- Apply the following CSS to transform the list items into a grid layout:
#element .e-list-item {
height: 100px;
width: 100px;
float: left;
}
Here’s a basic example of ListView with grid layout:
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { ListViewModule } from '@syncfusion/ej2-angular-lists'
import { Component, ViewChild } from '@angular/core';
@Component({
imports: [
ListViewModule
],
standalone: true,
selector: 'my-app',
template: `
<ejs-listview id='element' [dataSource]='data'>
<ng-template #template let-data="">
<img id="listImage" src="https://ej2.syncfusion.com/documentation/code-snippet/listview/grid-layout-cs1/apple.png" alt="apple" />
</ng-template>
</ejs-listview>
`,
})
export class AppComponent {
public data = [1, 2, 3, 4, 5, 6, 7, 8, 9];
}
@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';
@import 'node_modules/@syncfusion/ej2-angular-inputs/styles/material.css';
#element {
display: block;
max-width: 303px;
margin: auto;
border: 1px solid #dddddd;
border-radius: 3px;
}
#element .e-list-item {
height: 100px;
width: 100px;
float: left;
padding: 0;
}
#listImage {
width: 55px;
height: 55px;
margin-left: 20px;
margin-top: 20px;
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
Data Manipulation
The ListView component supports various data manipulation operations to manage list items effectively.
Add Item
Use the addItem
method to add new items to the ListView. The method accepts an array of items as its argument.
this.$refs.listViewInstance.addItem([{text: 'Apricot', id: '32'}]);
Remove Item
To remove items, use the removeItem
method. Pass either the item object with an id or the list item element as the argument.
this.$refs.listViewInstance.removeItem({id: '32'});
Sort Items
Enable sorting by setting the sortOrder
property to either ‘Ascending’ or ‘Descending’.
// In template
<ejs-listview [sortOrder]="'Ascending'" [dataSource]="data"></ejs-listview>
// In component
this.listViewInstance.sortOrder = 'Ascending'
Filter Items
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;
The following example demonstrates all these data manipulation features:
import { Component, ViewChild, ElementRef } from '@angular/core';
import { ListViewComponent, ListViewModule } from '@syncfusion/ej2-angular-lists';
import { DialogComponent, DialogModule } from '@syncfusion/ej2-angular-popups';
import { ButtonModule } from '@syncfusion/ej2-angular-buttons';
import { DataManager, Query } from '@syncfusion/ej2-data';
import { FormsModule } from '@angular/forms';
import { CommonModule } from '@angular/common';
interface FruitItem {
text: string;
id: string;
imgUrl: string;
}
@Component({
imports: [
ListViewModule,
DialogModule,
ButtonModule,
FormsModule,
CommonModule,
],
standalone: true,
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()' [(ngModel)]="searchText"/>
<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()' title="Sort fruits" data-ripple="true">
<span class="e-btn-icon e-icons" [ngClass]="{'e-sort-icon-ascending': !isDescending, 'e-sort-icon-descending': isDescending}"></span>
</button>
<button ejs-button id="add" class="e-control e-btn e-small e-round e-primary e-icon-btn" (click)='addItem()' 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>
<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" [(ngModel)]="newFruitName"/>
</div>
<div>
<label for="imgurl">Fruit Image: </label>
<input id="imgurl" class="e-input" type="text" placeholder="Enter image url" [(ngModel)]="newFruitImgUrl"/>
</div>
</div>
</ng-template>
</ejs-dialog>
</div>
<ejs-listview id='element' #listview [dataSource]='fruitsdata' [sortOrder]='currentSortOrder'>
<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" (click)="onDeleteBtnClick(data)" data-ripple="true">
<span class="e-btn-icon e-icons delete-icon"></span>
</button>
</div>
<div class="fruitName"></div>
</div>
</ng-template>
</ejs-listview>
</div>
`,
})
export class AppComponent {
@ViewChild('listview') listViewInstance!: ListViewComponent | any;
@ViewChild('dialogObj') dialogObj!: DialogComponent | any;
@ViewChild('searchEle') searchEle!: ElementRef;
public fruitsdata: FruitItem[] = [
{
text: 'Date',
id: '1',
imgUrl: 'https://ej2.syncfusion.com/documentation/code-snippet/listview/manipulation-cs1/dates.jpg',
},
{
text: 'Fig',
id: '2',
imgUrl: 'https://ej2.syncfusion.com/documentation/code-snippet/listview/manipulation-cs1/fig.jpg',
},
{
text: 'Apple',
id: '3',
imgUrl: 'https://ej2.syncfusion.com/documentation/code-snippet/listview/manipulation-cs1/apple.png',
},
{
text: 'Apricot',
id: '4',
imgUrl: 'https://ej2.syncfusion.com/documentation/code-snippet/listview/manipulation-cs1/apricot.jpg',
},
{
text: 'Grape',
id: '5',
imgUrl: 'https://ej2.syncfusion.com/documentation/code-snippet/listview/manipulation-cs1/grape.jpg',
},
{
text: 'Strawberry',
id: '6',
imgUrl: 'https://ej2.syncfusion.com/documentation/code-snippet/listview/manipulation-cs1/strawberry.jpg',
},
{
text: 'Pineapple',
id: '7',
imgUrl: 'https://ej2.syncfusion.com/documentation/code-snippet/listview/manipulation-cs1/pineapple.jpg',
},
{
text: 'Melon',
id: '8',
imgUrl: 'https://ej2.syncfusion.com/documentation/code-snippet/listview/manipulation-cs1/melon.jpg',
},
{
text: 'Lemon',
id: '9',
imgUrl: 'https://ej2.syncfusion.com/documentation/code-snippet/listview/manipulation-cs1/lemon.jpg',
},
{
text: 'Cherry',
id: '10',
imgUrl: 'https://ej2.syncfusion.com/documentation/code-snippet/listview/manipulation-cs1/cherry.jpg',
},
];
public dataManager: DataManager;
constructor() {
this.dataManager = new DataManager(this.fruitsdata);
}
public addButtons = [
{
click: this.dlgButtonClick.bind(this),
buttonModel: { content: 'Add', isPrimary: true },
},
];
public isDescending = false;
public currentSortOrder = 'Ascending';
public searchText = '';
public newFruitName = '';
public newFruitImgUrl = '';
addItem() {
this.newFruitName = '';
this.newFruitImgUrl = '';
this.dialogObj.show();
}
sortItems() {
this.isDescending = !this.isDescending;
this.currentSortOrder = this.isDescending ? 'Descending' : 'Ascending';
if (this.listViewInstance) {
this.listViewInstance.sortOrder = this.currentSortOrder;
}
}
onKeyUp() {
if (this.listViewInstance) {
if (this.searchText) {
this.listViewInstance.dataSource = new DataManager(
this.fruitsdata
).executeLocal(
new Query().where('text', 'startswith', this.searchText, true)
);
} else {
this.listViewInstance.dataSource = this.dataManager;
}
}
}
onDeleteBtnClick(data: FruitItem) {
if (this.listViewInstance) {
this.listViewInstance.removeItem(data);
}
this.fruitsdata = this.fruitsdata.filter((item) => item.id !== data.id);
this.dataManager = new DataManager(this.fruitsdata);
}
dlgButtonClick() {
const id = Math.random().toString(36).substr(2, 9);
const newFruit: FruitItem = {
text: this.newFruitName,
id: id,
imgUrl: this.newFruitImgUrl,
};
if (this.listViewInstance) {
this.listViewInstance.addItem([newFruit]);
}
this.fruitsdata.push(newFruit);
this.dataManager = new DataManager(this.fruitsdata);
this.dialogObj.hide();
}
}
@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';
@import 'node_modules/@syncfusion/ej2-angular-inputs/styles/material.css';
#listImage {
width: 55px;
height: 55px;
margin-left: 25px;
}
#sample {
max-width: 440px;
margin: auto;
box-shadow: 0 3px 6px lightgray;
}
.headerContainer {
height: 48px;
line-height: 48px;
background: rgb(2, 120, 215);
color: white;
margin-bottom: 3px;
}
.headerContainer .e-input-group {
margin-left: 20px;
width: 200px;
background: white;
height: 31px;
}
.headerContainer #search {
height: 21px;
margin-left: 10px;
}
#listDialog .input_name {
margin-bottom: 20px;
}
.headerContainer #add,
.headerContainer #sort {
float: right;
margin-right: 15px;
margin-top: 7px;
background: white;
color: black
}
.headerContainer .e-input-search::before {
font-family: 'e-icons';
content: '\e961';
margin-top: 3px;
}
/* csslint ignore:start */
.headerContainer .e-input-group .e-input-group-icon.e-input-search {
padding: 0 10px 0 10px;
}
#element .e-list-item {
height: 110px;
width: 110px;
float: left;
padding: 0;
position: relative;
user-select: none;
}
#element .e-delete-btn {
float: right;
visibility: hidden;
margin-top: -10px;
}
#element .e-delete-btn.e-btn.e-small.e-round {
width: 2em;
height: 2em;
}
#element .e-btn.e-small.e-round .e-btn-icon.delete-icon {
font-size: 9px;
}
#element .e-list-item:hover .e-delete-btn {
visibility: visible;
background: red;
border-radius: 50%;
}
#element .fruits {
height: inherit;
width: inherit;
padding: 10px 0 10px 0;
}
#element .fruitName {
text-align: center;
}
.headerContainer .e-add-icon::before {
content: '\e823';
}
#element .delete-icon::before {
content: '\e7fc';
color: white;
}
.headerContainer .e-sort-icon-ascending::before {
content: '\e840';
}
.headerContainer .e-sort-icon-descending::before {
content: '\e83f';
}
.e-dialog.e-control.e-popup.e-popup-open {
max-height: 361px !important;
}
/* csslint ignore:end */
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));