DataView

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


import { DataViewModule } from 'primeng/dataview';

DataView requires a value to display along with a list template that receives an object in the collection to return content.

Bamboo WatchINSTOCK
Accessories
Bamboo Watch
5
$65
Black WatchINSTOCK
Accessories
Black Watch
4
$72
Blue BandLOWSTOCK
Fitness
Blue Band
3
$79
Blue T-ShirtINSTOCK
Clothing
Blue T-Shirt
5
$29
BraceletINSTOCK
Accessories
Bracelet
4
$15

<p-dataView #dv [value]="products">
    <ng-template pTemplate="list" let-products>
        <div class="grid grid-nogutter">
            <div class="col-12" *ngFor="let item of products; let first = first" class="col-12">
                <div class="flex flex-column sm:flex-row sm:align-items-center p-4 gap-3" [ngClass]="{ 'border-top-1 surface-border': !first }">
                    <div class="md:w-10rem relative">
                        <img class="block xl:block mx-auto border-round w-full" [src]="'https://primefaces.org/cdn/primeng/images/demo/product/' + item.image" [alt]="item.name" />
                        <p-tag [value]="item.inventoryStatus" [severity]="getSeverity(item)" class="absolute" [style.left.px]="4" [style.top.px]="4" />
                    </div>
                    <div class="flex flex-column md:flex-row justify-content-between md:align-items-center flex-1 gap-4">
                        <div class="flex flex-row md:flex-column justify-content-between align-items-start gap-2">
                            <div>
                                <span class="font-medium text-secondary text-sm">{{ item.category }}</span>
                                <div class="text-lg font-medium text-900 mt-2">{{ item.name }}</div>
                            </div>
                            <div class="surface-100 p-1" style="border-radius: 30px">
                                <div class="surface-0 flex align-items-center gap-2 justify-content-center py-1 px-2" style="border-radius: 30px; box-shadow: 0px 1px 2px 0px rgba(0, 0, 0, 0.04), 0px 1px 2px 0px rgba(0, 0, 0, 0.06)">
                                    <span class="text-900 font-medium text-sm">{{ item.rating }}</span>
                                    <i class="pi pi-star-fill text-yellow-500"></i>
                                </div>
                            </div>
                        </div>
                        <div class="flex flex-column md:align-items-end gap-5">
                            <span class="text-xl font-semibold text-900">{{ '$' + item.price }}</span>
                            <div class="flex flex-row-reverse md:flex-row gap-2">
                                <p-button icon="pi pi-heart" [outlined]="true" />
                                <p-button icon="pi pi-shopping-cart" class="flex-auto md:flex-initial white-space-nowrap" label="Buy Now" [disabled]="item.inventoryStatus === 'OUTOFSTOCK'" />
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </ng-template>
</p-dataView>

Pagination is enabled with the paginator and rows properties. Refer to the Paginator for more information about customizing the paginator.

Bamboo WatchINSTOCK
Accessories
Bamboo Watch
5
$65
Black WatchINSTOCK
Accessories
Black Watch
4
$72
Blue BandLOWSTOCK
Fitness
Blue Band
3
$79
Blue T-ShirtINSTOCK
Clothing
Blue T-Shirt
5
$29
BraceletINSTOCK
Accessories
Bracelet
4
$15

<p-dataView #dv [value]="products" [rows]="5" [paginator]="true">
    <ng-template pTemplate="list" let-products>
        <div class="grid grid-nogutter">
            <div class="col-12" *ngFor="let item of products; let first = first" class="col-12">
                <div class="flex flex-column sm:flex-row sm:align-items-center p-4 gap-3" [ngClass]="{ 'border-top-1 surface-border': !first }">
                    <div class="md:w-10rem relative">
                        <img class="block xl:block mx-auto border-round w-full" [src]="'https://primefaces.org/cdn/primeng/images/demo/product/' + item.image" [alt]="item.name" />
                        <p-tag [value]="item.inventoryStatus" [severity]="getSeverity(item)" class="absolute" [style.left.px]="4" [style.top.px]="4" />
                    </div>
                    <div class="flex flex-column md:flex-row justify-content-between md:align-items-center flex-1 gap-4">
                        <div class="flex flex-row md:flex-column justify-content-between align-items-start gap-2">
                            <div>
                                <span class="font-medium text-secondary text-sm">{{ item.category }}</span>
                                <div class="text-lg font-medium text-900 mt-2">{{ item.name }}</div>
                            </div>
                            <div class="surface-100 p-1" style="border-radius: 30px">
                                <div class="surface-0 flex align-items-center gap-2 justify-content-center py-1 px-2" style="border-radius: 30px; box-shadow: 0px 1px 2px 0px rgba(0, 0, 0, 0.04), 0px 1px 2px 0px rgba(0, 0, 0, 0.06)">
                                    <span class="text-900 font-medium text-sm">{{ item.rating }}</span>
                                    <i class="pi pi-star-fill text-yellow-500"></i>
                                </div>
                            </div>
                        </div>
                        <div class="flex flex-column md:align-items-end gap-5">
                            <span class="text-xl font-semibold text-900">{{ '$' + item.price }}</span>
                            <div class="flex flex-row-reverse md:flex-row gap-2">
                                <p-button icon="pi pi-heart" [outlined]="true" />
                                <p-button icon="pi pi-shopping-cart" class="flex-auto md:flex-initial white-space-nowrap" label="Buy Now" [disabled]="item.inventoryStatus === 'OUTOFSTOCK'" />
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </ng-template>
</p-dataView>

Built-in sorting is controlled by bindings sortField and sortOrder properties from a custom UI.

Bamboo WatchINSTOCK
Accessories
Bamboo Watch
5
$65
Black WatchINSTOCK
Accessories
Black Watch
4
$72
Blue BandLOWSTOCK
Fitness
Blue Band
3
$79
Blue T-ShirtINSTOCK
Clothing
Blue T-Shirt
5
$29
BraceletINSTOCK
Accessories
Bracelet
4
$15

<p-dataView #dv [value]="products" [sortField]="sortField" [sortOrder]="sortOrder">
    <ng-template pTemplate="header">
        <div class="flex flex-column md:flex-row md:justify-content-between">
            <p-dropdown [options]="sortOptions" [(ngModel)]="sortKey" placeholder="Sort By Price" (onChange)="onSortChange($event)" styleClass="mb-2 md:mb-0" />
        </div>
    </ng-template>
        <ng-template pTemplate="list" let-products>
        <div class="grid grid-nogutter">
            <div class="col-12" *ngFor="let item of products; let first = first" class="col-12">
                <div class="flex flex-column sm:flex-row sm:align-items-center p-4 gap-3" [ngClass]="{ 'border-top-1 surface-border': !first }">
                    <div class="md:w-10rem relative">
                        <img class="block xl:block mx-auto border-round w-full" [src]="'https://primefaces.org/cdn/primeng/images/demo/product/' + item.image" [alt]="item.name" />
                        <p-tag [value]="item.inventoryStatus" [severity]="getSeverity(item)" class="absolute" [style.left.px]="4" [style.top.px]="4" />
                    </div>
                    <div class="flex flex-column md:flex-row justify-content-between md:align-items-center flex-1 gap-4">
                        <div class="flex flex-row md:flex-column justify-content-between align-items-start gap-2">
                            <div>
                                <span class="font-medium text-secondary text-sm">{{ item.category }}</span>
                                <div class="text-lg font-medium text-900 mt-2">{{ item.name }}</div>
                            </div>
                            <div class="surface-100 p-1" style="border-radius: 30px">
                                <div class="surface-0 flex align-items-center gap-2 justify-content-center py-1 px-2" style="border-radius: 30px; box-shadow: 0px 1px 2px 0px rgba(0, 0, 0, 0.04), 0px 1px 2px 0px rgba(0, 0, 0, 0.06)">
                                    <span class="text-900 font-medium text-sm">{{ item.rating }}</span>
                                    <i class="pi pi-star-fill text-yellow-500"></i>
                                </div>
                            </div>
                        </div>
                        <div class="flex flex-column md:align-items-end gap-5">
                            <span class="text-xl font-semibold text-900">{{ '$' + item.price }}</span>
                            <div class="flex flex-row-reverse md:flex-row gap-2">
                                <p-button icon="pi pi-heart" [outlined]="true" />
                                <p-button icon="pi pi-shopping-cart" class="flex-auto md:flex-initial white-space-nowrap" label="Buy Now" [disabled]="item.inventoryStatus === 'OUTOFSTOCK'" />
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </ng-template>
</p-dataView>

DataView supports list and grid display modes defined with the layout property. The helper DataViewLayoutOptions component can be used to switch between the modes however this component is optional and you may use your own UI to switch modes as well.

Bamboo WatchINSTOCK
Accessories
Bamboo Watch
5
$65
Black WatchINSTOCK
Accessories
Black Watch
4
$72
Blue BandLOWSTOCK
Fitness
Blue Band
3
$79
Blue T-ShirtINSTOCK
Clothing
Blue T-Shirt
5
$29
BraceletINSTOCK
Accessories
Bracelet
4
$15
Brown PurseOUTOFSTOCK
Accessories
Brown Purse
4
$120
Chakra BraceletLOWSTOCK
Accessories
Chakra Bracelet
3
$32
Galaxy EarringsINSTOCK
Accessories
Galaxy Earrings
5
$34
Game ControllerLOWSTOCK
Electronics
Game Controller
4
$99
Gaming SetINSTOCK
Electronics
Gaming Set
3
$299
Gold Phone CaseOUTOFSTOCK
Accessories
Gold Phone Case
4
$24
Green EarbudsINSTOCK
Electronics
Green Earbuds
4
$89

<p-dataView #dv [value]="products" [layout]="layout">
    <ng-template pTemplate="header">
        <div class="flex justify-content-end">
            <p-dataViewLayoutOptions [layout]="layout" />
        </div>
    </ng-template>
    <ng-template pTemplate="list" let-products>
        <div class="grid grid-nogutter">
            <div class="col-12" *ngFor="let item of products; let first = first" class="col-12">
                <div class="flex flex-column sm:flex-row sm:align-items-center p-4 gap-3" [ngClass]="{ 'border-top-1 surface-border': !first }">
                    <div class="md:w-10rem relative">
                        <img class="block xl:block mx-auto border-round w-full" [src]="'https://primefaces.org/cdn/primeng/images/demo/product/' + item.image" [alt]="item.name" />
                        <p-tag [value]="item.inventoryStatus" [severity]="getSeverity(item)" class="absolute" [style.left.px]="4" [style.top.px]="4" />
                    </div>
                    <div class="flex flex-column md:flex-row justify-content-between md:align-items-center flex-1 gap-4">
                        <div class="flex flex-row md:flex-column justify-content-between align-items-start gap-2">
                            <div>
                                <span class="font-medium text-secondary text-sm">{{ item.category }}</span>
                                <div class="text-lg font-medium text-900 mt-2">{{ item.name }}</div>
                            </div>
                            <div class="surface-100 p-1" style="border-radius: 30px">
                                <div class="surface-0 flex align-items-center gap-2 justify-content-center py-1 px-2" style="border-radius: 30px; box-shadow: 0px 1px 2px 0px rgba(0, 0, 0, 0.04), 0px 1px 2px 0px rgba(0, 0, 0, 0.06)">
                                    <span class="text-900 font-medium text-sm">{{ item.rating }}</span>
                                    <i class="pi pi-star-fill text-yellow-500"></i>
                                </div>
                            </div>
                        </div>
                        <div class="flex flex-column md:align-items-end gap-5">
                            <span class="text-xl font-semibold text-900">{{ '$' + item.price }}</span>
                            <div class="flex flex-row-reverse md:flex-row gap-2">
                                <p-button icon="pi pi-heart" [outlined]="true" />
                                <p-button icon="pi pi-shopping-cart" class="flex-auto md:flex-initial white-space-nowrap" label="Buy Now" [disabled]="item.inventoryStatus === 'OUTOFSTOCK'" />
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </ng-template>
    <ng-template let-product pTemplate="grid" let-products>
        <div class="grid grid-nogutter">
            <div class="col-12 sm:col-6 md:col-4 xl:col-6 p-2" *ngFor="let product of products">
                <div class="p-4 border-1 surface-border surface-card border-round flex flex-column">
                    <div class="surface-50 flex justify-content-center border-round p-3">
                        <div class="relative mx-auto">
                            <img class="border-round w-full" [src]="'https://primefaces.org/cdn/primeng/images/demo/product/' + product.image" [alt]="product.name" style="max-width: 300px;" />
                            <p-tag [value]="product.inventoryStatus" [severity]="getSeverity(product)" class="absolute" [style.left.px]="4" [style.top.px]="4" />
                        </div>
                    </div>
                    <div class="pt-4">
                        <div class="flex flex-row justify-content-between align-items-start gap-2">
                            <div>
                                <span class="font-medium text-secondary text-sm">{{ product.category }}</span>
                                <div class="text-lg font-medium text-900 mt-1">{{ product.name }}</div>
                            </div>
                            <div class="surface-100 p-1" style="border-radius: 30px">
                                <div class="surface-0 flex align-items-center gap-2 justify-content-center py-1 px-2" style="border-radius: 30px; box-shadow: 0px 1px 2px 0px rgba(0, 0, 0, 0.04), 0px 1px 2px 0px rgba(0, 0, 0, 0.06)">
                                    <span class="text-900 font-medium text-sm">{{ product.rating }}</span>
                                    <i class="pi pi-star-fill text-yellow-500"></i>
                                </div>
                            </div>
                        </div>
                        <div class="flex flex-column gap-4 mt-4">
                            <span class="text-2xl font-semibold">{{ '$' + product.price }}</span>
                            <div class="flex gap-2">
                                <p-button icon="pi pi-shopping-cart" class="flex-auto md:flex-initial white-space-nowrap" label="Buy Now" [disabled]="product.inventoryStatus === 'OUTOFSTOCK'" />
                                <p-button icon="pi pi-heart" [outlined]="true" />
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </ng-template>
</p-dataView>

While data is being loaded. Skeleton component may be used to indicate the busy state.


<p-dataView #dv [value]="products" [layout]="layout">
    <ng-template pTemplate="header">
        <div class="flex justify-content-end">
            <p-dataViewLayoutOptions [layout]="layout" />
        </div>
    </ng-template>
    <ng-template pTemplate="list" let-products>
        <div class="grid grid-nogutter">
            <div class="col-12" *ngFor="let i of counterArray(6); let first = first" class="col-12">
                <div class="flex flex-column xl:flex-row xl:align-items-start p-4 gap-4" [ngClass]="{ 'border-top-1 surface-border': !first }">
                    <p-skeleton styleClass="w-9 sm:w-16rem xl:w-10rem h-6rem block xl:block mx-auto border-round" />
                    <div class="flex flex-column sm:flex-row justify-content-between align-items-center xl:align-items-start flex-1 gap-4">
                        <div class="flex flex-column align-items-center sm:align-items-start gap-3">
                            <p-skeleton styleClass="w-8rem border-round h-2rem" />
                            <p-skeleton styleClass="w-6rem border-round h-1rem" />
                            <div class="flex align-items-center gap-3">
                                <p-skeleton styleClass="w-6rem border-round h-1rem" />
                                <p-skeleton styleClass="w-3rem border-round h-1rem" />
                            </div>
                        </div>
                        <div class="flex sm:flex-column align-items-center sm:align-items-end gap-3 sm:gap-2">
                            <p-skeleton styleClass="w-4rem border-round h-2rem" />
                            <p-skeleton shape="circle" styleClass="w-3rem h-3rem" />
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </ng-template>
    <ng-template let-product pTemplate="grid" let-products>
        <div class="grid grid-nogutter">
            <div class="col-12 sm:col-6 md:col-4 xl:col-6 p-2" *ngFor="let i of counterArray(6)">
                <div class="p-4 border-1 surface-border surface-card border-round">
                    <div class="flex flex-wrap align-items-center justify-content-between gap-2">
                        <p-skeleton styleClass="w-6rem border-round h-2rem" />
                        <p-skeleton styleClass="w-3rem border-round h-1rem" />
                    </div>
                    <div class="flex flex-column align-items-center gap-3 py-5">
                        <p-skeleton styleClass="w-9 border-round h-10rem" />
                        <p-skeleton styleClass="w-8rem border-round h-2rem" />
                        <p-skeleton styleClass="w-6rem border-round h-1rem" />
                    </div>
                    <div class="flex align-items-center justify-content-between">
                        <p-skeleton styleClass="w-4rem border-round h-2rem" />
                        <p-skeleton shape="circle" styleClass="w-3rem h-3rem" />
                    </div>
                </div>
            </div>
        </div>
    </ng-template>
</p-dataView>

Following is the list of structural style classes, for theming classes visit theming page.

NameElement
p-dataviewContainer element.
p-dataview-listContainer element in list layout.
p-dataview-gridContainer element in grid layout.
p-dataview-headerHeader section.
p-dataview-footerFooter section.
p-dataview-contentContainer of items.
p-dataview-emptymessageEmpty message element.

Screen Reader

The container element that wraps the layout options buttons has a group role whereas each button element uses button role and aria-pressed is updated depending on selection state. Values to describe the buttons are derived from the aria.listView and aria.gridView properties of the locale API respectively.

Refer to paginator accessibility documentation for the paginator of the component.

Keyboard Support

KeyFunction
tabMoves focus to the buttons.
spaceToggles the checked state of a button.