Angular DataView

Angular DataView

·

9 min read

Angular DataView displays data in grid or list layout with pagination and sorting features.

Setup

Refer to PrimeNG setup documentation for download and installation steps for your environment.

Import

import {DataViewModule} from 'primeng/dataview';

PrimeFlex

DataView utilizes PrimeFlex so it is required to be installed in your application. Refer to the documentation for details.

Getting Started

DataView requires a collection of items as its value and one or more templates depending on the layout mode e.g. list and grid.

Throughout the samples, a car interface having vin, brand, year and color properties are used to define an object to be displayed by the dataview. Cars are loaded by a CarService that connects to a server to fetch the cars.

export interface Car {
    vin;
    year;
    brand;
    color;
}
import {Injectable} from 'angular2/core';
import {Http, Response} from 'angular2/http';
import {Car} from '../domain/car';

@Injectable()
export class CarService {

    constructor(private http: Http) {}

    getCarsLarge() {
        return this.http.get('/showcase/resources/data/cars-large.json')
                    .toPromise()
                    .then(res => <Car[]> res.json().data)
                    .then(data => { return data; });
    }
}
export class DataViewDemo implements OnInit {

    cars: Car[];

    constructor(private carService: CarService) { }

    ngOnInit() {
        this.carService.getCarsLarge().then(cars => this.cars = cars);
    }
}
<p-dataView [value]="cars">
    <ng-template let-car pTemplate="listItem">
        <div>
            {{car.id}}
        </div>
    </ng-template>
</p-dataView>

Layouts

DataView has two layout modes; "list" and "grid" where a separate template is used to render an item in each mode. In list mode name of the template is "listItem" whereas in grid mode it is "gridItem". In grid mode, the ng-template element should contain a div element as a wrapper with PrimeFlex style class of your choice.

Note that there is no restriction to use both layouts at the same time, you may configure only one layout using the layout property with the corresponding ng-template.

<p-dataView [value]="cars">
    <ng-template let-car pTemplate="listItem">
        <div>
            {{car.id}}
        </div>
    </ng-template>
    <ng-template let-car pTemplate="gridItem">
        <div class="p-col-12 p-md-3">
            {{car.year}}
        </div>
    </ng-template>
</p-dataView>

Sections

Header and Footers sections can be customized using header and footer templates.

<p-dataView [value]="cars">
    <ng-template pTemplate="header">List of Cars</ng-template>
    <ng-template let-car pTemplate="listItem">
        <div>
            {{car.id}}
        </div>
    </ng-template>
    <ng-template let-car pTemplate="gridItem">
        <div class="p-col-12 p-md-3">
            {{car.year}}
        </div>
    </ng-template>
    <ng-template pTemplate="footer">Choose from the list.</ng-template>
</p-dataView>

DataViewLayoutOptions

When both layout modes are enabled in DataView, a UI element would be necessary to let the user toggle between the view. p-dataViewLayoutOptions is a helper component to display a buttonset to choose the layout mode in DataView. Location of the p-dataViewLayoutOptions should be inside the DataView component. If you prefer a different UI element you can create your own that updates the layout property of the DataView.

<p-dataView [value]="cars">
    <ng-template pTemplate="header">
        <p-dataViewLayoutOptions></p-dataViewLayoutOptions>
    </ng-template>
    <ng-template let-car pTemplate="listItem">
        <div>
            {{car.id}}
        </div>
    </ng-template>
    <ng-template let-car pTemplate="gridItem">
        <div class="p-col-12 p-md-3">
            {{car.year}}
        </div>
    </ng-template>
    <ng-template pTemplate="footer">
        <p-dataViewLayoutOptions></p-dataViewLayoutOptions>
    </ng-template>
</p-dataView>

Paginator

Pagination is enabled by setting paginator property to true, rows attribute defines the number of rows per page and pageLinks specify the the number of page links to display. To customize the paginator, use paginatorLeftTemplate, paginatorRightTemplate and paginatorDropdownItemTemplate templates.

<p-dataView [value]="cars" [paginator]="true" [rows]="10">
    <ng-template let-car pTemplate="listItem">
        <div>
            {{car.id}}
        </div>
    </ng-template>
    <ng-template let-car pTemplate="gridItem">
        <div class="p-col-12 p-md-3">
            {{car.year}}
        </div>
    </ng-template>
    <ng-template pTemplate="paginatorleft" let-state>
        {{state.first}}
        <button type="button" pButton icon="pi-refresh"></button>
    </ng-template>
    <ng-template pTemplate="paginatorright">
        <button type="button" pButton icon="pi-cloud-upload"></button>
    </ng-template>
    <ng-template let-item pTemplate="paginatordropdownitem">
        {{item.value}} - per page
    </ng-template>
</p-dataView>

Lazy Loading

Lazy mode is handy to deal with large datasets, instead of loading the entire data, small chunks of data is loaded by invoking onLazyLoad callback everytime paging happens. To implement lazy loading, enable lazy attribute and provide a method callback using onLazyLoad that actually loads the data from a remote datasource. onLazyLoad gets an event object that contains information about what to load. It is also important to assign the logical number of rows to totalRecords by doing a projection query for paginator configuration so that paginator displays the UI assuming there are actually records of totalRecords size although in reality they aren't as in lazy mode, only the records that are displayed on the current page exist.

<p-dataView [value]="cars" [paginator]="true" [rows]="10"
    [lazy]="true" (onLazyLoad)="loadData($event)" [totalRecords]="totalRecords">
    <ng-template let-car pTemplate="listItem">
        <div>
            {{car.id}}
        </div>
    </ng-template>
    <ng-template let-car pTemplate="gridItem">
        <div class="p-col-12 p-md-3">
            {{car.year}}
        </div>
    </ng-template>
</p-dataView>
loadData(event) {
    //event.first = First row offset
    //event.rows = Number of rows per page
}

Sorting

sortField and sortOrder properties are available for sorting functionality, for flexibility there is no built-in UI available so that a custom UI can be used for the sorting element. Here is an example that uses a dropdown where simply updating the sortField - sortOrder bindings of the DataView initiates sorting.

<p-dataView [value]="cars" [sortField]="sortField" [sortOrder]="sortOrder">
    <ng-template pTemplate="header">
        <p-dropdown [options]="sortOptions" [(ngModel)]="sortKey" placeholder="Sort By"
            (onChange)="onSortChange($event)" [style]="{'min-width':'15em'}"></p-dropdown>
    </ng-template>
    <ng-template let-car pTemplate="listItem">
        <div>
            {{car.id}}
        </div>
    </ng-template>
    <ng-template let-car pTemplate="gridItem">
        <div class="p-col-12 p-md-3">
            {{car.year}}
        </div>
    </ng-template>
</p-dataView>
export class DataViewSortDemo implements OnInit {

    cars: Car[];

    sortOptions: SelectItem[];

    sortKey: string;

    sortField: string;

    sortOrder: number;

    constructor(private carService: CarService) { }

    ngOnInit() {
        this.carService.getCarsLarge().then(cars => this.cars = cars);

        this.sortOptions = [
            {label: 'Newest First', value: '!year'},
            {label: 'Oldest First', value: 'year'},
            {label: 'Brand', value: 'brand'}
        ];
    }

    onSortChange(event) {
        let value = event.value;

        if (value.indexOf('!') === 0) {
            this.sortOrder = -1;
            this.sortField = value.substring(1, value.length);
        }
        else {
            this.sortOrder = 1;
            this.sortField = value;
        }
    }
}

Filtering

Filtering is implemented by defining the filterBy property, match mode parameters and calling the filter function of the component, for flexibility there is no built-in UI available so that a custom UI can be used for the filter element. Available match modes are "contains"(Default), "startsWith", "endsWith", "equals", "notEquals", "in", "lt", "lte", "gt" and "gte". Here is an example that uses an input field. filterBy is a string and multiple fields can be defined with a comma separated list.

<p-dataView #dv [value]="cars" filterBy="brand">
    <ng-template pTemplate="header">
        <input type="search" pInputText placeholder="Search by brand" (input)="dv.filter($event.target.value, "contains")">
    </ng-template>
    <ng-template let-car pTemplate="listItem">
        {{car.id}}
    </ng-template>
    <ng-template let-car pTemplate="gridItem">
        {{car.year}}
    </ng-template>
</p-dataView>

Custom UI Elements

As mentioned above, layout options selector, sorting and filtering are baked-in and no strict UI is enforces to make it possible to come up with your own UI elements to enable these features.

Loading Status

DataView has a loading property, when enabled a spinner icon is displayed to indicate data load. An optional loadingIcon property can be passed in case you'd like a different loading icon.

<p-dataview [value]="cars" [loading]="loading">
    //content
</p-dataview>

Theming

DataView supports various themes featuring Material, Bootstrap, Fluent as well as your own custom themes via the Designer tool.

Resources

Visit the PrimeNG DataView showcase for demos and documentation.