DataView displays data in grid or list layout with pagination and sorting features.
import DataView from 'primevue/dataview';
import DataViewLayoutOptions from 'primevue/dataviewlayoutoptions' // optional
DataView requires a value to display along with a list slot that receives an object in the collection to return content.
<DataView :value="products">
<template #list="slotProps">
<div class="flex flex-wrap">
<div v-for="(item, index) in slotProps.items" :key="index" class="w-full p-3">
<div class="flex flex-col xl:flex-row xl:items-start p-4 gap-4" :class="{ 'border-t border-surface-200 dark:border-surface-700': index !== 0 }">
<img class="w-9/12 sm:w-[16rem] xl:w-[10rem] shadow-md block xl:block mx-auto rounded" :src="`https://primefaces.org/cdn/primevue/images/product/${item.image}`" :alt="item.name" />
<div class="flex flex-col sm:flex-row justify-between items-center xl:items-start flex-1 gap-4">
<div class="flex flex-col items-center sm:items-start gap-3">
<div class="text-2xl font-bold text-surface-900 dark:text-surface-0">{{ item.name }}</div>
<Rating :modelValue="item.rating" readonly :cancel="false"></Rating>
<div class="flex items-center gap-3">
<span class="flex items-center gap-2">
<i class="pi pi-tag"></i>
<span class="font-semibold">{{ item.category }}</span>
</span>
<Tag :value="item.inventoryStatus" :severity="getSeverity(item)"></Tag>
</div>
</div>
<div class="flex sm:flex-col items-center sm:items-end gap-3 sm:gap-2">
<span class="text-2xl font-semibold">${{ item.price }}</span>
<Button icon="pi pi-shopping-cart" rounded :disabled="item.inventoryStatus === 'OUTOFSTOCK'"></Button>
</div>
</div>
</div>
</div>
</div>
</template>
</DataView>
Pagination is enabled with the paginator and rows properties. Refer to the Paginator for more information about customizing the paginator.
<DataView :value="products" paginator :rows="5">
<template #list="slotProps">
<div class="flex flex-wrap">
<div v-for="(item, index) in slotProps.items" :key="index" class="w-full p-3">
<div class="flex flex-col xl:flex-row xl:items-start p-4 gap-4" :class="{ 'border-t border-surface-200 dark:border-surface-700': index !== 0 }">
<img class="w-9/12 sm:w-[16rem] xl:w-[10rem] shadow-md block xl:block mx-auto rounded" :src="`https://primefaces.org/cdn/primevue/images/product/${item.image}`" :alt="item.name" />
<div class="flex flex-col sm:flex-row justify-between items-center xl:items-start flex-1 gap-4">
<div class="flex flex-col items-center sm:items-start gap-3">
<div class="text-2xl font-bold text-surface-900 dark:text-surface-0">{{ item.name }}</div>
<Rating :modelValue="item.rating" readonly :cancel="false"></Rating>
<div class="flex items-center gap-3">
<span class="flex items-center gap-2">
<i class="pi pi-tag"></i>
<span class="font-semibold">{{ item.category }}</span>
</span>
<Tag :value="item.inventoryStatus" :severity="getSeverity(item)"></Tag>
</div>
</div>
<div class="flex sm:flex-col items-center sm:items-end gap-3 sm:gap-2">
<span class="text-2xl font-semibold">${{ item.price }}</span>
<Button icon="pi pi-shopping-cart" rounded :disabled="item.inventoryStatus === 'OUTOFSTOCK'"></Button>
</div>
</div>
</div>
</div>
</div>
</template>
</DataView>
Built-in sorting is controlled by bindings sortField and sortField properties from a custom UI.
<DataView :value="products" :sortOrder="sortOrder" :sortField="sortField">
<template #header>
<Dropdown v-model="sortKey" :options="sortOptions" optionLabel="label" placeholder="Sort By Price" @change="onSortChange($event)" />
</template>
<template #list="slotProps">
<div class="flex flex-wrap">
<div v-for="(item, index) in slotProps.items" :key="index" class="w-full p-3">
<div class="flex flex-col xl:flex-row xl:items-start p-4 gap-4" :class="{ 'border-t border-surface-200 dark:border-surface-700': index !== 0 }">
<img class="w-9/12 sm:w-[16rem] xl:w-[10rem] shadow-md block xl:block mx-auto rounded" :src="`https://primefaces.org/cdn/primevue/images/product/${item.image}`" :alt="item.name" />
<div class="flex flex-col sm:flex-row justify-between items-center xl:items-start flex-1 gap-4">
<div class="flex flex-col items-center sm:items-start gap-3">
<div class="text-2xl font-bold text-surface-900 dark:text-surface-0">{{ item.name }}</div>
<Rating :modelValue="item.rating" readonly :cancel="false"></Rating>
<div class="flex items-center gap-3">
<span class="flex items-center gap-2">
<i class="pi pi-tag"></i>
<span class="font-semibold">{{ item.category }}</span>
</span>
<Tag :value="item.inventoryStatus" :severity="getSeverity(item)"></Tag>
</div>
</div>
<div class="flex sm:flex-col items-center sm:items-end gap-3 sm:gap-2">
<span class="text-2xl font-semibold">${{ item.price }}</span>
<Button icon="pi pi-shopping-cart" rounded :disabled="item.inventoryStatus === 'OUTOFSTOCK'"></Button>
</div>
</div>
</div>
</div>
</div>
</template>
</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.
<DataView :value="products" :layout="layout">
<template #header>
<div class="flex justify-end">
<DataViewLayoutOptions v-model="layout" />
</div>
</template>
<template #list="slotProps">
<div class="flex flex-wrap">
<div v-for="(item, index) in slotProps.items" :key="index" class="w-full p-3">
<div class="flex flex-col xl:flex-row xl:items-start p-4 gap-4" :class="{ 'border-t border-surface-200 dark:border-surface-700': index !== 0 }">
<img class="w-9/12 sm:w-[16rem] xl:w-[10rem] shadow-md block xl:block mx-auto rounded" :src="`https://primefaces.org/cdn/primevue/images/product/${item.image}`" :alt="item.name" />
<div class="flex flex-col sm:flex-row justify-between items-center xl:items-start flex-1 gap-4">
<div class="flex flex-col items-center sm:items-start gap-3">
<div class="text-2xl font-bold text-surface-900 dark:text-surface-0">{{ item.name }}</div>
<Rating :modelValue="item.rating" readonly :cancel="false"></Rating>
<div class="flex items-center gap-3">
<span class="flex items-center gap-2">
<i class="pi pi-tag"></i>
<span class="font-semibold">{{ item.category }}</span>
</span>
<Tag :value="item.inventoryStatus" :severity="getSeverity(item)"></Tag>
</div>
</div>
<div class="flex sm:flex-col items-center sm:items-end gap-3 sm:gap-2">
<span class="text-2xl font-semibold">${{ item.price }}</span>
<Button icon="pi pi-shopping-cart" rounded :disabled="item.inventoryStatus === 'OUTOFSTOCK'"></Button>
</div>
</div>
</div>
</div>
</div>
</template>
<template #grid="slotProps">
<div class="flex flex-wrap">
<div v-for="(item, index) in slotProps.items" :key="index" class="w-full p-3 sm:w-6/12 xl:w-4/12">
<div class="p-4 border border-surface-200 dark:border-surface-700 bg-surface-0 dark:bg-surface-800 rounded">
<div class="flex flex-wrap items-center justify-between gap-2">
<div class="flex items-center gap-2">
<i class="pi pi-tag"></i>
<span class="font-semibold">{{ item.category }}</span>
</div>
<Tag :value="item.inventoryStatus" :severity="getSeverity(item)"></Tag>
</div>
<div class="flex flex-col items-center gap-3 py-5">
<img class="w-9/12 shadow-md rounded" :src="`https://primefaces.org/cdn/primevue/images/product/${item.image}`" :alt="item.name" />
<div class="text-2xl font-bold">{{ item.name }}</div>
<Rating :modelValue="item.rating" readonly :cancel="false"></Rating>
</div>
<div class="flex items-center justify-between">
<span class="text-2xl font-semibold">${{ item.price }}</span>
<Button icon="pi pi-shopping-cart" rounded :disabled="item.inventoryStatus === 'OUTOFSTOCK'"></Button>
</div>
</div>
</div>
</div>
</template>
</DataView>
While data is being loaded. Skeleton component may be used to indicate the busy state.
<DataView :value="products" :layout="layout">
<template #header>
<div class="flex justify-end">
<DataViewLayoutOptions v-model="layout" />
</div>
</template>
<template #list>
<div class="flex flex-wrap">
<div v-for="i in 6" :key="i" class="w-full p-3">
<div class="flex flex-col xl:flex-row xl:items-start p-4 gap-4" :class="{ 'border-t border-surface-200 dark:border-surface-700': i !== 0 }">
<Skeleton class="w-9/12 sm:w-[16rem] xl:w-[10rem] shadow-md h-6rem block xl:block mx-auto rounded" />
<div class="flex flex-col sm:flex-row justify-between items-center xl:items-start flex-1 gap-4">
<div class="flex flex-col items-center sm:items-start gap-3">
<Skeleton class="w-[8rem] rounded h-[2rem]" />
<Skeleton class="w-[6rem] rounded h-[1rem]" />
<div class="flex items-center gap-3">
<Skeleton class="w-[6rem] rounded h-[1rem]" />
<Skeleton class="w-[3rem] rounded h-[1rem]" />
</div>
</div>
<div class="flex sm:flex-col items-center sm:items-end gap-3 sm:gap-2">
<Skeleton class="w-[4rem] rounded h-[2rem]" />
<Skeleton shape="circle" class="w-[3rem] h-[3rem]" />
</div>
</div>
</div>
</div>
</div>
</template>
<template #grid>
<div class="flex flex-wrap">
<div v-for="i in 6" :key="i" class="w-full p-3 sm:w-6/12 xl:w-4/12">
<div class="p-4 border border-surface-200 dark:border-surface-700 bg-surface-0 dark:bg-surface-800 rounded">
<div class="flex flex-wrap items-center justify-between gap-2">
<Skeleton class="w-[6rem] rounded h-[2rem]" />
<Skeleton class="w-[3rem] rounded h-[1rem]" />
</div>
<div class="flex flex-col items-center gap-3 py-5">
<Skeleton class="w-9/12 shadow-md rounded h-10rem" />
<Skeleton class="w-[8rem] rounded h-[2rem]" />
<Skeleton class="w-[6rem] rounded h-[1rem]" />
</div>
<div class="flex items-center justify-between">
<Skeleton class="w-[4rem] rounded h-[2rem]" />
<Skeleton shape="circle" class="w-[3rem] h-[3rem]" />
</div>
</div>
</div>
</div>
</template>
</DataView>
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.
Key | Function |
---|---|
tab | Moves focus to the buttons. |
space | Toggles the checked state of a button. |