Search results

Customize listview as grid layout in JavaScript ListView control

08 Dec 2021 / 5 minutes to read

In Listview, list items can be rendered in grid layout with following data manipulations.

  • Add Item
  • Remove Item
  • Sort Items
  • Filter Items

Grid Layout

In this section, we will discuss about rendering of list items in grid layout.

  • Initialize and render ListView with dataSource which will render list items in list layout.
  • Now, add the below CSS to list item. This will make list items to render in grid layout
Copied to clipboard
#default-list .e-list-item {
    height: 100px;
    width: 100px;
    float: left;
}

In the below sample, we have rendered List items in grid layout.

Source
Preview
index.ts
index.html
Copied to clipboard
import { ListView } from '@syncfusion/ej2-lists';

//define the array of string
let data: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9];

//Initialize ListView control
let listViewInstance: ListView = new ListView({
//set the data to datasource property
dataSource: data,
//set the template for list items
template: '<img id="listImage" src="./apple.png" alt="apple" />'
});

//Render initialized ListView
listViewInstance.appendTo("#element");
Copied to clipboard
<!DOCTYPE html>
<html lang="en">

<head>
    <title>Essential JS 2 for 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 ListView UI Control" />
    <meta name="author" content="Syncfusion" />
    <link href="index.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-base/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-lists/styles/material.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
    <script src="systemjs.config.js"></script>
</head>

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

</html>

Data manipulation

In this section, we will discuss about ListView data manipulations.

Add Item

We can add list item using addItem API. This will accept array of data as argument.

Copied to clipboard
 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.

Remove item

We can remove list item using removeItem API. This will accept fields with id or list item element as argument.

Copied to clipboard
 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.

Sort Items

Listview can be sorted either in Ascending or Descending order. To enable sorting in your ListView, set sortOrder as Ascending or Descending.

Copied to clipboard
let listViewInstance: ListView = new ListView({
sortOrder: 'Ascending';
})

We can also set sorting after control initialization.

Copied to clipboard
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.

Filter Items

Listview data can be filtered with the help of dataManager. After filtering the data, update ListView dataSource with filtered data.

Copied to clipboard
let value = document.getElementById("filter").value;  //input text box value
let filteredData = new DataManager(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.

Source
Preview
index.ts
index.html
index.css
Copied to clipboard
import { ListView, SelectedItem } from '@syncfusion/ej2-lists';
import { Dialog } from '@syncfusion/ej2-popups';
import { closest, enableRipple, MouseEventArgs } from '@syncfusion/ej2-base';
import { DataManager, Query } from "@syncfusion/ej2-data";
enableRipple(true);

let ascClass = 'e-sort-icon-ascending';
let desClass = 'e-sort-icon-descending';

//define the array of JSON
let fruitsdata: { [key: string]: Object }[] = [
{ 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' },
];

//Initialize ListView control
let listViewInstance: ListView = new ListView({

//set the data to datasource property
dataSource: fruitsdata.slice(),

//set the template for list items
template: '<div class="fruits"><div class="first"><img id="listImage" src="${imgUrl}" alt="fruit" /><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">${text}</div></div>',

//set sortOrder for list items
sortOrder: 'Ascending',
actionComplete: () => {
    wireEvents();
}

});

//Render initialized ListView
listViewInstance.appendTo('#element');

let dialogObj: Dialog = new Dialog({
header: 'Add fruit',
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"/></div><div><label for="imgurl">Fruit Image: </label><input id="imgurl" class="e-input" type="text" placeholder="Enter image url"/></div></div>',
showCloseIcon: true,
buttons: [{
    click: dlgButtonClick,
    buttonModel: { content: 'Add', isPrimary: true }
}],
width: '300px',
visible: false
});

dialogObj.appendTo('#dialog');

function addItem() {
(document.getElementById("name") as HTMLInputElement).value = "";
(document.getElementById("imgurl") as HTMLInputElement).value = "";
dialogObj.show()
}

function wireEvents() {
Array.prototype.forEach.call(document.getElementsByClassName('e-delete-btn'), (ele: HTMLButtonElement) => {
    ele.addEventListener('click', onDeleteBtnClick);
});
document.getElementById("add").addEventListener('click', addItem);
document.getElementById("sort").addEventListener('click', sortItems);
document.getElementById("search").addEventListener("keyup", onKeyUp);
}

//Here we are removing list item
function onDeleteBtnClick(e: MouseEventArgs) {
e.stopPropagation();
let li: Element = closest(e.currentTarget as Element, '.e-list-item');
let data = listViewInstance.findItem(li);
listViewInstance.removeItem(data as any);
new DataManager(fruitsdata).remove('id', { id: (<{ [key: string]: any }>data)["id"] });
}

//Here we are adding list item
function dlgButtonClick() {
let name: string = (document.getElementById("name") as HTMLInputElement).value;
let url: string = (document.getElementById("imgurl") as HTMLInputElement).value;
let id: number = Math.random() * 10000;
listViewInstance.addItem([{ text: name, id: id, imgUrl: url }]);
fruitsdata.push({ text: name, id: id, imgUrl: url });
listViewInstance.element.querySelector('[data-uid="' + id + '"]').getElementsByClassName('e-delete-btn')[0].addEventListener('click', onDeleteBtnClick);
dialogObj.hide();
}

//Here we are sorting list item
function sortItems() {
let ele: Element = document.getElementById("sort").firstElementChild;
let des = ele.classList.contains(desClass) ? true : false;
if (des) {
    ele.classList.remove(desClass);
    ele.classList.add(ascClass);
    listViewInstance.sortOrder = 'Ascending'
} else {
    ele.classList.remove(ascClass);
    ele.classList.add(desClass);
    listViewInstance.sortOrder = 'Descending'
}
listViewInstance.dataBind();
wireEvents();
}

//Here, the list items are filtered using the DataManager instance.
function onKeyUp() {
let value: string = (document.getElementById("search") as HTMLInputElement).value;
let data: Object[] = new DataManager(fruitsdata).executeLocal(
    new Query().where("text", "startswith", value, true)
);
if (!value) {
    listViewInstance.dataSource = fruitsdata.slice();
} else {
    listViewInstance.dataSource = data as { [key: string]: Object }[];
    listViewInstance.dataBind();
}
}
Copied to clipboard
<!DOCTYPE html>
<html lang="en">

<head>
    <title>Essential JS 2 for 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 ListView UI Control" />
    <meta name="author" content="Syncfusion" />
    <link href="index.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-base/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-lists/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-buttons/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-popups/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-inputs/styles/material.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
    <script src="systemjs.config.js"></script>
</head>

<body>
    <div id='loader'>Loading....</div>
    <div id='container'>
        <div class="headerContainer">
            <div class="e-input-group">
                <input id="search" class="e-input" type="text" placeholder="Search fruits" />
                <span class="e-input-group-icon e-input-search"></span>
            </div>
            <button id="sort" class="e-control e-btn e-small e-round e-primary e-icon-btn" title="Sort fruits" data-ripple="true">
                <span class="e-btn-icon e-icons e-sort-icon-ascending"></span>
            </button>
            <button id="add" class="e-control e-btn e-small e-round e-primary e-icon-btn" title="Add fruit" data-ripple="true">
                <span class="e-btn-icon e-icons e-add-icon"></span>
            </button>
            <div id="dialog"></div>
        </div>
        <div id='element'></div>
    </div>
</body>

</html>
Copied to clipboard
#container {
    visibility: hidden;
}

#loader {
  color: #008cff;
  height: 40px;
  width: 30%;
  position: absolute;
  font-family: 'Helvetica Neue','calibiri';
  font-size: 14px;
  top: 45%;
  left: 45%;
}

#listImage {
    width: 55px;
    height: 55px;
    margin-left: 25px;
}

#container {
    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;
}

.headerContainer .e-input-group .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;
    width: 2em;
    height: 2em;
}

#element .e-round .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';
}