DataViewDataView displays data in grid or list layout with pagination, sorting and filtering features.
Documentation
Import
import {DataViewModule} from 'primeng/dataview';
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 Grid CSS 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="ui-g-12 ui-md-3">
{{car.year}}
</div>
</ng-template>
</p-dataView>
Sections
Header and Footer are the two sections that are capable of displaying custom content.
<p-dataView [value]="cars">
<p-header>List of Cars</p-header>
<p-footer>Choose from the list.</p-footer>
<ng-template let-car pTemplate="listItem">
<div>
{{car.id}}
</div>
</ng-template>
<ng-template let-car pTemplate="gridItem">
<div class="ui-g-12 ui-md-3">
{{car.year}}
</div>
</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">
<p-header>
<p-dataViewLayoutOptions></p-dataViewLayoutOptions>
</p-header>
<p-footer>
<p-dataViewLayoutOptions></p-dataViewLayoutOptions>
</p-footer>
<ng-template let-car pTemplate="listItem">
<div>
{{car.id}}
</div>
</ng-template>
<ng-template let-car pTemplate="gridItem">
<div class="ui-g-12 ui-md-3">
{{car.year}}
</div>
</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 left and right side of the paginators, use "paginatorLeftTemplate" and "paginatorRightTemplate" 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="ui-g-12 ui-md-3">
{{car.year}}
</div>
</ng-template>
<ng-template pTemplate="paginatorleft" let-state>
{{state.first}}
<button type="button" pButton icon="fa-refresh"></button>
</ng-template>
<ng-template pTemplate="paginatorright">
<button type="button" pButton icon="fa-cloud-upload"></button>
</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="ui-g-12 ui-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">
<p-header>
<p-dropdown [options]="sortOptions" [(ngModel)]="sortKey" placeholder="Sort By"
(onChange)="onSortChange($event)" [style]="{'min-width':'15em'}"></p-dropdown>
</p-header>
<ng-template let-car pTemplate="listItem">
<div>
{{car.id}}
</div>
</ng-template>
<ng-template let-car pTemplate="gridItem">
<div class="ui-g-12 ui-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 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. 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">
<p-header>
<input type="search" pInputText placeholder="Search by brand" (keyup)="dv.filter($event.target.value)">
</p-header>
<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>
Properties
Name | Type | Default | Description |
---|---|---|---|
value | array | null | An array of objects to display. |
layout | string | list | Layout of the items, valid values are "list" and "grid". |
paginator | boolean | false | When specified as true, enables the pagination. |
rows | number | null | Number of rows to display per page. |
totalRecords | number | null | Number of total records, defaults to length of value when not defined. |
pageLinks | number | 5 | Number of page links to display in paginator. |
rowsPerPageOptions | array | null | Array of integer values to display inside rows per page dropdown of paginator |
paginatorPosition | string | bottom | Position of the paginator, options are "top","bottom" or "both". |
alwaysShowPaginator | boolean | true | Whether to show it even there is only one page. |
paginatorDropdownAppendTo | any | null | Target element to attach the paginator dropdown overlay, valid values are "body" or a local ng-template variable of another element. |
currentPageReportTemplate | string | {currentPage} of {totalPages} | Text to display the current page information. |
showCurrentPageReport | boolean | false | Whether to display current page report. |
lazy | boolean | false | Defines if data is loaded and interacted with in lazy manner. |
emptyMessage | string | No records found. | Text to display when there is no data. |
style | string | null | Inline style of the component. |
styleClass | string | null | Style class of the component. |
trackBy | Function | null | Function to optimize the dom operations by delegating to ngForTrackBy, default algoritm checks for object identity. |
filterBy | string | null | Comma separated list of fields in the object graph to search against. |
loading | boolean | false | Displays a loader to indicate data load is in progress. |
loadingIcon | string | fa-circle-o-notch | The icon to show while indicating data load is in progress. |
first | number | 0 | Index of the first row to be displayed. |
Events
Name | Parameters | Description |
---|---|---|
onLazyLoad | event.first = First row offset event.rows = Number of rows per page | Callback to invoke when paging, sorting or filtering happens in lazy mode. |
onPage | event.first: Index of first record in page event.rows: Number of rows on the page | Callback to invoke when pagination occurs. |
onSort | event.field: Name of the sort field. event.order: Order of the sort. | Callback to invoke when sorting occurs. |
Styling
Following is the list of structural style classes, for theming classes visit theming page.
Name | Element |
---|---|
ui-dataview | Container element. |
ui-dataview-header | Header section. |
ui-dataview-footer | Footer section. |
ui-dataview-content | Container of items. |
ui-table-loading | Loader mask. |
ui-dataview-loading | Loader background. |
ui-dataview-loading-content | Loader content. |
ui-dataview-emptymessage | Empty message element. |
Dependencies
None.
Source
<p-dataView #dv [value]="cars" [paginator]="true" [rows]="20" paginatorPosition="both" filterBy="brand"
[sortField]="sortField" [sortOrder]="sortOrder">
<p-header>
<div class="ui-helper-clearfix">
<div class="ui-g">
<div class="ui-g-12 ui-md-4">
<p-dropdown [options]="sortOptions" [(ngModel)]="sortKey" placeholder="Sort By" (onChange)="onSortChange($event)" [style]="{'min-width':'140px'}"></p-dropdown>
</div>
<div class="ui-g-6 ui-md-4 filter-container">
<div style="position:relative">
<input type="search" pInputText placeholder="Search by brand" (keyup)="dv.filter($event.target.value)">
</div>
</div>
<div class="ui-g-6 ui-md-4" style="text-align:right">
<p-dataViewLayoutOptions></p-dataViewLayoutOptions>
</div>
</div>
</div>
</p-header>
<ng-template let-car pTemplate="listItem">
<div class="ui-g" style="padding: 2em;border-bottom: 1px solid #d9d9d9">
<div class="ui-g-12 ui-md-3" style="text-align:center">
<img src="assets/showcase/images/demo/car/{{car.brand}}.png">
</div>
<div class="ui-g-12 ui-md-8 car-details">
<div class="ui-g">
<div class="ui-g-2 ui-sm-6">Vin: </div>
<div class="ui-g-10 ui-sm-6"><b>{{car.vin}}</b></div>
<div class="ui-g-2 ui-sm-6">Year: </div>
<div class="ui-g-10 ui-sm-6"><b>{{car.year}}</b></div>
<div class="ui-g-2 ui-sm-6">Brand: </div>
<div class="ui-g-10 ui-sm-6"><b>{{car.brand}}</b></div>
<div class="ui-g-2 ui-sm-6">Color: </div>
<div class="ui-g-10 ui-sm-6"><b>{{car.color}}</b></div>
</div>
</div>
<div class="ui-g-12 ui-md-1 search-icon">
<button pButton type="button" icon="pi pi-search" (click)="selectCar($event, car)"></button>
</div>
</div>
</ng-template>
<ng-template let-car pTemplate="gridItem">
<div style="padding:.5em" class="ui-g-12 ui-md-3">
<p-panel [header]="car.vin" [style]="{'text-align':'center'}">
<img src="assets/showcase/images/demo/car/{{car.brand}}.png" width="60">
<div class="car-detail">{{car.year}} - {{car.color}}</div>
<hr class="ui-widget-content" style="border-top:0">
<button pButton type="button" icon="pi pi-search" (click)="selectCar($event, car)" style="margin-top:0"></button>
</p-panel>
</div>
</ng-template>
</p-dataView>
<p-dialog header="Car Details" [(visible)]="displayDialog" [responsive]="true" showEffect="fade" [modal]="true" [style]="{width: '225px'}" (onAfterHide)="onDialogHide()">
<div class="ui-g" *ngIf="selectedCar">
<div class="ui-g-12" style="text-align:center">
<img src="assets/showcase/images/demo/car/{{selectedCar.brand}}.png">
</div>
<div class="ui-g-4">Vin: </div>
<div class="ui-g-8">{{selectedCar.vin}}</div>
<div class="ui-g-4">Brand: </div>
<div class="ui-g-8">{{selectedCar.brand}}</div>
<div class="ui-g-4">Year: </div>
<div class="ui-g-8">{{selectedCar.year}}</div>
<div class="ui-g-4">Color: </div>
<div class="ui-g-8">{{selectedCar.color}}</div>
</div>
</p-dialog>
export class DataViewDemo implements OnInit {
cars: Car[];
selectedCar: Car;
displayDialog: boolean;
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'}
];
}
selectCar(event: Event, car: Car) {
this.selectedCar = car;
this.displayDialog = true;
event.preventDefault();
}
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;
}
}
onDialogHide() {
this.selectedCar = null;
}
}