pull/12/head
cagataycivici 2019-05-13 14:24:51 +03:00
commit 7c6480f440
23 changed files with 2200 additions and 20 deletions

9
.gitignore vendored
View File

@ -2,6 +2,15 @@
node_modules
/dist
# misc
/.sass-cache
/connect.lock
/coverage
/libpeerconnection.log
npm-debug.log
testem.log
/typings
# local env files
.env.local
.env.*.local

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,54 @@
{
"data":[
{"vin":"a1653d4d","brand":"VW","year":1998,"color":"White","price":10000},
{"vin":"ddeb9b10","brand":"Mercedes","year":1985,"color":"Green","price":25000},
{"vin":"d8ebe413","brand":"Jaguar","year":1979,"color":"Silver","price":30000},
{"vin":"aab227b7","brand":"Audi","year":1970,"color":"Black","price":12000},
{"vin":"631f7412","brand":"Volvo","year":1992,"color":"Red","price":15500},
{"vin":"7d2d22b0","brand":"VW","year":1993,"color":"Maroon","price":40000},
{"vin":"50e900ca","brand":"Fiat","year":1964,"color":"Blue","price":25000},
{"vin":"4bbcd603","brand":"Renault","year":1983,"color":"Maroon","price":22000},
{"vin":"70214c7e","brand":"Renault","year":1961,"color":"Black","price":19000},
{"vin":"ec229a92","brand":"Audi","year":1984,"color":"Brown","price":36000},
{"vin":"1083ee40","brand":"VW","year":1984,"color":"Silver","price":215000},
{"vin":"6e0da3ab","brand":"Volvo","year":1987,"color":"Silver","price":32000},
{"vin":"5aee636b","brand":"Jaguar","year":1995,"color":"Maroon","price":20000},
{"vin":"7cc43997","brand":"Jaguar","year":1984,"color":"Orange","price":14000},
{"vin":"88ec9f66","brand":"Honda","year":1989,"color":"Maroon","price":36000},
{"vin":"f5a4a5f5","brand":"BMW","year":1986,"color":"Blue","price":28000},
{"vin":"15b9a5c9","brand":"Mercedes","year":1986,"color":"Orange","price":14000},
{"vin":"f7e18d01","brand":"Mercedes","year":1991,"color":"White","price":25000},
{"vin":"cec593d7","brand":"VW","year":1992,"color":"Blue","price":36000},
{"vin":"d5bac4f0","brand":"Renault","year":2001,"color":"Blue","price":25000},
{"vin":"56b527c8","brand":"Jaguar","year":1990,"color":"Yellow","price":52000},
{"vin":"1ac011ff","brand":"Audi","year":1966,"color":"Maroon","price":45000},
{"vin":"fc074185","brand":"BMW","year":1962,"color":"Blue","price":54000},
{"vin":"606ba663","brand":"Honda","year":1982,"color":"Blue","price":22000},
{"vin":"d05060b8","brand":"Mercedes","year":2003,"color":"Silver","price":15000},
{"vin":"46e4bbe8","brand":"Mercedes","year":1986,"color":"White","price":18000},
{"vin":"c29da0d7","brand":"BMW","year":1983,"color":"Brown","price":32000},
{"vin":"24622f70","brand":"VW","year":1973,"color":"Maroon","price":36000},
{"vin":"7f573d2c","brand":"Mercedes","year":1991,"color":"Red","price":21000},
{"vin":"b69e6f5c","brand":"Jaguar","year":1993,"color":"Yellow","price":16000},
{"vin":"ead9bf1d","brand":"Fiat","year":1968,"color":"Maroon","price":43000},
{"vin":"bc58113e","brand":"Renault","year":1981,"color":"Silver","price":36000},
{"vin":"2989d5b1","brand":"Honda","year":2006,"color":"Blue","price":240000},
{"vin":"c243e3a0","brand":"Fiat","year":1990,"color":"Maroon","price":15000},
{"vin":"e3d3ebf3","brand":"Audi","year":1996,"color":"White","price":28000},
{"vin":"45337e7a","brand":"Mercedes","year":1982,"color":"Blue","price":14000},
{"vin":"36e9cf7e","brand":"Fiat","year":2000,"color":"Orange","price":26000},
{"vin":"036bf135","brand":"Mercedes","year":1973,"color":"Black","price":22000},
{"vin":"ad612e9f","brand":"Mercedes","year":1975,"color":"Red","price":45000},
{"vin":"97c6e1e9","brand":"Volvo","year":1967,"color":"Green","price":42000},
{"vin":"ae962274","brand":"Volvo","year":1982,"color":"Red","price":36000},
{"vin":"81f8972a","brand":"BMW","year":2007,"color":"Black","price":56000},
{"vin":"f8506743","brand":"Audi","year":1975,"color":"Blue","price":42000},
{"vin":"596859d1","brand":"Fiat","year":2002,"color":"Green","price":48000},
{"vin":"d83c1d9a","brand":"Volvo","year":1972,"color":"Black","price":29000},
{"vin":"32f41550","brand":"Mercedes","year":1978,"color":"Brown","price":17000},
{"vin":"c28cd2e4","brand":"Volvo","year":1982,"color":"Silver","price":24000},
{"vin":"80890dcc","brand":"Audi","year":1962,"color":"White","price":36000},
{"vin":"4bf1aeb5","brand":"VW","year":2000,"color":"Silver","price":24000},
{"vin":"45ca4786","brand":"BMW","year":1995,"color":"Maroon","price":50000}
]
}

View File

@ -0,0 +1,14 @@
{
"data": [
{"brand": "VW", "year": 2012, "color": "Orange", "vin": "dsad231ff"},
{"brand": "Audi", "year": 2011, "color": "Black", "vin": "gwregre345"},
{"brand": "Renault", "year": 2005, "color": "Gray", "vin": "h354htr"},
{"brand": "BMW", "year": 2003, "color": "Blue", "vin": "j6w54qgh"},
{"brand": "Mercedes", "year": 1995, "color": "Orange", "vin": "hrtwy34"},
{"brand": "Volvo", "year": 2005, "color": "Black", "vin": "jejtyj"},
{"brand": "Honda", "year": 2012, "color": "Yellow", "vin": "g43gr"},
{"brand": "Jaguar", "year": 2013, "color": "Orange", "vin": "greg34"},
{"brand": "Ford", "year": 2000, "color": "Black", "vin": "h54hw5"},
{"brand": "Fiat", "year": 2013, "color": "Red", "vin": "245t2s"}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -50,6 +50,7 @@
</a>
<div :class="{'submenuhide': activeMenuIndex !== 2, 'submenushow': activeMenuIndex === 2}">
<div>
<router-link to="/dataview">&#9679; DataView</router-link>
<router-link to="/fullcalendar">&#9679; FullCalendar</router-link>
<router-link to="/paginator">&#9679; Paginator</router-link>
</div>

View File

@ -5,6 +5,7 @@
@import '../../components/card/Card.css';
@import '../../components/checkbox/Checkbox.css';
@import '../../components/chips/Chips.css';
@import '../../components/dataview/DataView.css';
@import '../../components/dialog/Dialog.css';
@import '../../components/dropdown/Dropdown.css';
@import '../../components/fieldset/Fieldset.css';

View File

@ -143,7 +143,7 @@ export default {
this.focus();
this.hideOverlay();
},
onMultiContainerClick(event) {
onMultiContainerClick() {
this.focus();
},
removeItem(event, index) {

View File

@ -0,0 +1,41 @@
.p-dataview .p-paginator {
text-align: center;
}
.p-dataview-column {
padding: .25em;
}
.p-dataview-content-empty {
padding: .25em .625em;
}
.p-dataview .p-dataview-header,
.p-dataview .p-dataview-footer {
text-align: center;
padding: .5em .75em;
}
.p-dataview .p-dataview-header {
border-bottom: 0 none;
}
.p-dataview .p-dataview-footer {
border-top: 0 none;
}
.p-dataview .p-paginator-top {
border-bottom: 0 none;
}
.p-dataview .p-paginator-bottom {
border-top: 0 none;
}
.p-dataview.p-dataview-list > .p-dataview-content > div.p-grid > div {
width: 100%;
}
.p-dataview-loading-icon {
font-size: 2em;
}

View File

@ -0,0 +1,208 @@
<template>
<div :class="containerClass">
<div class="p-dataview-header" v-if="$scopedSlots.header">
<slot name="header"></slot>
</div>
<Paginator v-if="paginatorTop" :rows.sync="rows" :first.sync="firstRecord" :totalRecords="getTotalRecords" :pageLinkSize="pageLinkSize" :template="paginatorTemplate" :rowsPerPageOptions="rowsPerPageOptions"
:currentPageReportTemplate="currentPageReportTemplate" :class="{'p-paginator-top': paginatorTop}">
<template #left v-if="$scopedSlots.paginatorLeft">
<slot name="paginatorLeft"></slot>
</template>
<template #right v-if="$scopedSlots.paginatorRight">
<slot name="paginatorRight"></slot>
</template>
</Paginator>
<div class="p-dataview-content">
<div class="p-grid">
<template v-for="(data,index) of (templateItems)">
<slot v-if="$scopedSlots.listItem && layout === 'list'" name="listItem" :data="data" :index="index"></slot>
<slot v-if="$scopedSlots.gridItem && layout === 'grid'" name="gridItem" :data="data" :index="index"></slot>
</template>
<div v-if="isEmpty" class="p-col-12">{{emptyMessage}}</div>
</div>
</div>
<Paginator v-if="paginatorBottom" :rows.sync="rows" :first.sync="firstRecord" :totalRecords="getTotalRecords" :pageLinkSize="pageLinkSize" :template="paginatorTemplate" :rowsPerPageOptions="rowsPerPageOptions"
:currentPageReportTemplate="currentPageReportTemplate" :class="{'p-paginator-bottom': paginatorBottom}">
<template #left v-if="$scopedSlots.paginatorLeft">
<slot name="paginatorLeft"></slot>
</template>
<template #right v-if="$scopedSlots.paginatorRight">
<slot name="paginatorRight"></slot>
</template>
</Paginator>
<div class="p-dataview-footer" v-if="$scopedSlots.footer">
<slot name="footer"></slot>
</div>
</div>
</template>
<script>
import ObjectUtils from '../utils/ObjectUtils';
export default {
props: {
value: {
type: Array,
default: null
},
layout: {
type: String,
default: 'list'
},
rows: {
type: Number,
default: null
},
first: {
type: Number,
default: 0
},
totalRecords: {
type: Number,
default: null
},
paginator: {
type: Boolean,
default: false
},
paginatorPosition: {
type: String,
default: 'bottom'
},
alwaysShowPaginator: {
type: Boolean,
default: true
},
paginatorTemplate: {
type: String,
default: 'FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink'
},
pageLinkSize: {
type: Number,
default: 5
},
rowsPerPageOptions: {
type: Array,
default: null
},
currentPageReportTemplate: {
type: String,
default: '({currentPage} of {totalPages})'
},
emptyMessage: {
type: String,
default: 'No records found'
},
sortField: {
type: String,
default: null
},
sortOrder: {
type: Number,
default: null
},
lazy: {
type: Boolean,
default: false
}
},
data() {
return {
firstRecord: this.first ? this.first : 0
}
},
methods: {
processData() {
let data = this.value;
if (data && data.length) {
if (this.sortField) {
data = this.sort();
}
}
return data;
},
sort() {
if (this.value) {
const value = [...this.value];
value.sort((data1, data2) => {
let value1 = ObjectUtils.resolveFieldData(data1, this.sortField);
let value2 = ObjectUtils.resolveFieldData(data2, this.sortField);
let result = null;
if (value1 == null && value2 != null)
result = -1;
else if (value1 != null && value2 == null)
result = 1;
else if (value1 == null && value2 == null)
result = 0;
else if (typeof value1 === 'string' && typeof value2 === 'string')
result = value1.localeCompare(value2, undefined, { numeric: true });
else
result = (value1 < value2) ? -1 : (value1 > value2) ? 1 : 0;
return (this.sortOrder * result);
});
return value;
}
else {
return null;
}
}
},
computed: {
containerClass() {
return ['p-dataview p-component', {
'p-dataview-list': (this.layout === 'list'),
'p-dataview-grid': (this.layout === 'grid')
}
]
},
getTotalRecords() {
if (this.totalRecords)
return this.totalRecords;
else
return this.value ? this.value.length : 0;
},
isEmpty() {
return (!this.value || this.value.length === 0);
},
paginatorTop() {
if(this.paginatorPosition && (this.paginatorPosition !== 'bottom' || this.paginatorPosition === 'both')) {
return true
}
else
return null;
},
paginatorBottom() {
if(this.paginatorPosition && (this.paginatorPosition !== 'top' || this.paginatorPosition === 'both')) {
return true
}
else
return null;
},
templateItems (){
let value = this.processData();
if (value && value.length) {
if (this.paginator) {
const rows = this.rows;
const first = this.lazy ? 0 : this.firstRecord;
const last = rows + first;
let items = [];
for (let i = first; i < last; i++) {
items.push(value[i]);
}
return items;
}
else {
return value;
}
}
else return null;
}
}
}
</script>

View File

@ -0,0 +1,41 @@
<template>
<div class="p-dataview-layout-options p-selectbutton p-buttonset">
<button :class="buttonListClass" @click="changeLayout($event,'list')">
<i class="pi pi-bars p-button-icon-left"></i>
<span class="p-button-text p-clickable">p-btn</span>
</button>
<button :class="buttonGridClass" @click="changeLayout($event,'grid')">
<i class="pi pi-th-large p-button-icon-left"></i>
<span class="p-button-text p-clickable">p-btn</span>
</button>
</div>
</template>
<script>
export default {
props: {
layout: {
type: String,
default: null
}
},
computed: {
buttonListClass(){
return [
'p-button p-button-icon-only',
{'p-highlight': this.layout === 'list'}
]
},
buttonGridClass(){
return [
'p-button p-button-icon-only',
{'p-highlight': this.layout === 'grid'}
]
}
},
methods: {
changeLayout(event, layoutMode){
this.$emit('change', {originalEvent: event, value: layoutMode});
}
}
}
</script>

View File

@ -60,11 +60,13 @@ export default {
},
quill: null,
watch: {
value(newValue) {
value(newValue, oldValue) {
if (newValue !== oldValue && this.quill && !this.quill.hasFocus()) {
this.renderValue(newValue);
}
}
},
mounted() {
mounted() {
this.quill = new Quill(this.$refs.editorElement, {
modules: {
toolbar: this.$refs.toolbarElement

View File

@ -251,7 +251,7 @@ export default {
bindOutsideClickListener() {
if (!this.outsideClickListener) {
this.outsideClickListener = (event) => {
if (this.overlayVisible && this.$refs.overlay && !this.$refs.overlay.contains(event.target)) {
if (this.overlayVisible && this.isOutsideClicked(event)) {
this.overlayVisible = false;
}
};
@ -264,6 +264,9 @@ export default {
this.outsideClickListener = null;
}
},
isOutsideClicked(event) {
return !(this.$refs.container.isSameNode(event.target) || this.$refs.container.contains(event.target) || (this.$refs.overlay && this.$refs.overlay.contains(event.target)));
},
getLabelByValue(val) {
let label = null;

View File

@ -17,9 +17,9 @@
return (
<span class="p-paginator-pages">
{
this.value.map((pageLink, i) => {
return <button key={pageLink} class={['p-paginator-page p-paginator-element p-link', {
'p-highlight': ((pageLink - 1) === this.page)}]} on-click={e => this.onPageLinkClick(e, pageLink)}>{pageLink}</button>
this.value.map(pageLink => {
return (<button key={pageLink} class={['p-paginator-page p-paginator-element p-link', {
'p-highlight': ((pageLink - 1) === this.page)}]} on-click={e => this.onPageLinkClick(e, pageLink)}>{pageLink}</button>)
})
}
</span>

View File

@ -78,6 +78,8 @@ export default {
},
computed: {
listeners() {
let vm = this;
return {
...this.$listeners,
input: event => this.$emit('input', event.target.value),
@ -87,8 +89,8 @@ export default {
this.createPanel();
}
this.panel.style.zIndex = String(DomHandler.generateZIndex());
this.panel.style.display = 'block';
vm.panel.style.zIndex = String(DomHandler.generateZIndex());
vm.panel.style.display = 'block';
setTimeout(() => {
DomHandler.addClass(this.panel, 'p-input-overlay-visible');
DomHandler.removeClass(this.panel, 'p-input-overlay-hidden');
@ -104,7 +106,7 @@ export default {
DomHandler.removeClass(this.panel, 'p-input-overlay-visible');
setTimeout(() => {
this.panel.style.display = 'none';
vm.panel.style.display = 'none';
DomHandler.removeClass(this.panel, 'p-input-overlay-hidden');
}, 150);
}
@ -138,8 +140,8 @@ export default {
}
}
this.meter.style.backgroundPosition = meterPos;
this.info.textContent = label;
vm.meter.style.backgroundPosition = meterPos;
vm.info.textContent = label;
}
this.$emit('keyup', event);

View File

@ -1,7 +1,7 @@
<template>
<div class="p-selectbutton p-buttonset p-component p-buttonset">
<div v-for="(option, i) of options" :key="getOptionLabel(option)" :aria-label="getOptionLabel(option)"
@click="onOptionSelect($event, option, i)" @keydown.enter.prevent="onOptionSelect($event, option, i)" @keydown.space.prevent="onOptionSelect($event, option, i)"
@click="onOptionSelect($event, option, i)" @keydown.enter.prevent="onOptionSelect($event, option, i)" @keydown.space.prevent="onOptionSelect($event, option)"
:tabindex="isOptionDisabled(option) ? null : '0'" @focus="onFocus($event, i)" @blur="onBlur($event)"
:class="['p-button p-component p-button-text-only', {'p-highlight': isSelected(option), 'p-disabled': isOptionDisabled(option), 'p-focus': (i === focusedIndex)}]">
<slot name="option" :option="option" :index="i">
@ -41,7 +41,7 @@ export default {
isOptionDisabled(option) {
return this.optionDisabled ? ObjectUtils.resolveFieldData(option, this.optionDisabled) : false;
},
onOptionSelect(event, option, index) {
onOptionSelect(event, option) {
if (this.disabled || this.isOptionDisabled(option)) {
return;
}

View File

@ -278,8 +278,9 @@ export default {
handleStyle() {
if (this.horizontal)
return {'left': this.handlePosition + '%'};
else if (this.vertical)
else
return {'bottom': this.handlePosition + '%'};
},
handlePosition() {
if (this.value === 0)
@ -306,13 +307,13 @@ export default {
rangeStartHandleStyle() {
if (this.horizontal)
return {'left': this.rangeStartPosition + '%'};
else if (this.vertical)
else
return {'bottom': this.rangeStartPosition + '%'};
},
rangeEndHandleStyle() {
if (this.horizontal)
return {'left': this.rangeEndPosition + '%'};
else if (this.vertical)
else
return {'bottom': this.rangeEndPosition + '%'};
},
}

View File

@ -124,16 +124,18 @@ export default {
},
computed: {
listeners() {
let vm = this;
return {
...this.$listeners,
input: event => {
this.$emit('input', event.target.value)
},
focus: event => {
this.focused = true;
focus: () => {
vm.focused = true;
},
blur: event => {
this.focused = false;
vm.focused = false;
const parsedValue = this.parseValue(event.target.value);
this.$emit('input', parsedValue);

View File

@ -10,6 +10,8 @@ import Card from './components/card/Card';
import Chart from './components/chart/Chart';
import Checkbox from './components/checkbox/Checkbox';
import Chips from './components/chips/Chips';
import DataView from './components/dataview/DataView';
import DataViewLayoutOptions from './components/dataview/DataViewLayoutOptions';
import Dialog from './components/dialog/Dialog';
import Dropdown from './components/dropdown/Dropdown';
import Editor from './components/editor/Editor';
@ -63,6 +65,8 @@ Vue.component('Card', Card);
Vue.component('Chart', Chart);
Vue.component('Checkbox', Checkbox);
Vue.component('Chips', Chips);
Vue.component('DataView', DataView);
Vue.component('DataViewLayoutOptions', DataViewLayoutOptions);
Vue.component('Dialog', Dialog);
Vue.component('Dropdown', Dropdown);
Vue.component('Editor', Editor);

View File

@ -85,6 +85,11 @@ export default new Router({
path: '/chips',
name: 'chips',
component: () => import('./views/chips/ChipsDemo.vue')
},
{
path: '/dataview',
name: 'dataview',
component: () => import('./views/dataview/DataViewDemo.vue')
},
{
path: '/dialog',

16
src/service/CarService.js Normal file
View File

@ -0,0 +1,16 @@
import axios from 'axios'
export default class CarService {
getCarsSmall() {
return axios.get('demo/data/cars-small.json').then(res => res.data.data);
}
getCarsMedium() {
return axios.get('demo/data/cars-medium.json').then(res => res.data.data);
}
getCarsLarge() {
return axios.get('demo/data/cars-large.json').then(res => res.data.data);
}
}

View File

@ -0,0 +1,115 @@
<template>
<div>
<div class="content-section introduction">
<div class="feature-intro">
<h1>DataView</h1>
<p>DataView displays data in grid or list layout with pagination and sorting features.</p>
</div>
</div>
<div class="content-section implementation">
<h3 class="first">Default</h3>
<DataView :value="cars" :layout="layout" paginatorPosition='both' :paginator="true" :rows="20" :sortOrder="sortOrder" :sortField="sortField">
<template #header>
<div class="p-grid">
<div class="p-col-6" style="text-align: left">
<Dropdown v-model="sortKey" :options="sortOptions" optionLabel="label" placeholder="Sort By" @change="onSortChange($event)"/>
</div>
<div class="p-col-6" style="text-align: right">
<DataViewLayoutOptions :layout="layout" @change="changeMode"></DataViewLayoutOptions>
</div>
</div>
</template>
<template #listItem="slotProps" >
<div class="p-col-12 car-details" style="padding: 2em; border-bottom: 1px solid #d9d9d9">
<div class="p-grid">
<div class="p-col-12 p-md-3">
<img :src="'/demo/images/car/' + slotProps.data.brand + '.png'" :alt="slotProps.data.brand"/>
</div>
<div class="p-col-12 p-md-8 car-data">
<div>Vin: <b>{{slotProps.data.vin}}</b></div>
<div>Year: <b>{{slotProps.data.year}}</b></div>
<div>Brand: <b>{{slotProps.data.brand}}</b></div>
<div>Color: <b>{{slotProps.data.color}}</b></div>
</div>
<div class="p-col-12 p-md-1 search-icon" style="margin-top: 40px">
<Button icon="pi pi-search"></Button>
</div>
</div>
</div>
</template>
<template #gridItem="slotProps">
<div style="padding: .5em" class="p-col-12 p-md-3">
<Panel :header="slotProps.data.vin" style="text-align: center">
<img :src="'/demo/images/car/' + slotProps.data.brand + '.png'" :alt="slotProps.data.brand"/>
<div class="car-detail">{{slotProps.data.year}} - {{slotProps.data.color}}</div>
<hr class="ui-widget-content" style="border-top: 0" />
<Button icon="pi pi-search"></Button>
</Panel>
</div>
</template>
</DataView>
</div>
<DataViewDoc />
</div>
</template>
<script>
import CarService from '../../service/CarService';
import DataViewDoc from './DataViewDoc';
export default {
data() {
return {
cars: null,
layout: 'list',
sortKey: null,
sortOrder: null,
sortField: null,
sortOptions: [
{label: 'Newest First', value: '!year'},
{label: 'Oldest First', value: 'year'},
{label: 'Brand', value: 'brand'}
]
}
},
carService: null,
created() {
this.carService = new CarService();
},
mounted() {
this.carService.getCarsLarge().then(data => this.cars = data);
},
methods: {
changeMode(event) {
this.layout = event.value;
},
onSortChange(event){
const value = event.value.value;
const sortValue = event.value;
if (value.indexOf('!') === 0) {
this.sortOrder = -1;
this.sortField = value.substring(1, value.length);
this.sortKey = sortValue;
}
else {
this.sortOrder = 1;
this.sortField = value;
this.sortKey = sortValue;
}
}
},
components: {
'DataViewDoc': DataViewDoc
}
}
</script>
<style lang="scss">
.p-dropdown {
width: 12em;
}
</style>

View File

@ -0,0 +1,457 @@
<template>
<div class="content-section documentation">
<TabView>
<TabPanel header="Documentation">
<h3>Import</h3>
<CodeHighlight lang="javascript">
import DataView from 'primevue/dataview';
</CodeHighlight>
<h3>Getting Started</h3>
<p>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.</p>
<CodeHighlight lang="js">
<template v-pre>
data() {
return {
cars: null,
}
},
carService: null,
created() {
this.carService = new CarService();
},
mounted() {
this.carService.getCarsLarge().then(data => this.cars = data);
}
</template>
</CodeHighlight>
<h3>Layouts</h3>
<p>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".</p>
<p>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 template.</p>
<CodeHighlight>
<template v-pre>
&lt;template #listItem=&quot;slotProps&quot; &gt;
&lt;div class=&quot;p-col-12 car-details&quot; style=&quot;padding: 2em; border-bottom: 1px solid #d9d9d9&quot;&gt;
&lt;div class=&quot;p-grid&quot;&gt;
&lt;div class=&quot;p-col-12 p-md-3&quot;&gt;
&lt;img :src=&quot;'/demo/images/car/' + slotProps.data.brand + '.png'&quot; :alt=&quot;slotProps.data.brand&quot;/&gt;
&lt;/div&gt;
&lt;div class=&quot;p-col-12 p-md-8 car-data&quot;&gt;
&lt;div&gt;Vin: &lt;b&gt;{{slotProps.data.vin}}&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;Year: &lt;b&gt;{{slotProps.data.year}}&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;Brand: &lt;b&gt;{{slotProps.data.brand}}&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;Color: &lt;b&gt;{{slotProps.data.color}}&lt;/b&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;p-col-12 p-md-1 search-icon&quot; style=&quot;margin-top: 40px&quot;&gt;
&lt;Button icon=&quot;pi pi-search&quot;&gt;&lt;/Button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/template&gt;
&lt;template #gridItem=&quot;slotProps&quot;&gt;
&lt;div style=&quot;padding: .5em&quot; class=&quot;p-col-12 p-md-3&quot;&gt;
&lt;Panel :header=&quot;slotProps.data.vin&quot; style=&quot;text-align: center&quot;&gt;
&lt;img :src=&quot;'/demo/images/car/' + slotProps.data.brand + '.png'&quot; :alt=&quot;slotProps.data.brand&quot;/&gt;
&lt;div class=&quot;car-detail&quot;&gt;{{slotProps.data.year}} - {{slotProps.data.color}}&lt;/div&gt;
&lt;hr class=&quot;ui-widget-content&quot; style=&quot;border-top: 0&quot; /&gt;
&lt;Button icon=&quot;pi pi-search&quot;&gt;&lt;/Button&gt;
&lt;/Panel&gt;
&lt;/div&gt;
&lt;/template&gt;
</template>
</CodeHighlight>
<h3>Sections</h3>
<p>Header and Footer are the two sections that are capable of displaying custom content.</p>
<CodeHighlight>
&lt;template #header&gt;List of Cars&lt;/template&gt;
</CodeHighlight>
<h3>DataViewLayoutOptions</h3>
<p>When both layout modes are enabled in DataView, a UI element would be necessary to let the user toggle between the view. DataViewLayoutOptions is a helper component
to display a buttonset to choose the layout mode in DataView. Location of the 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>
<CodeHighlight>
&lt;template #header&gt;
&lt;DataViewLayoutOptions :layout=&quot;layout&quot; @change=&quot;changeMode&quot;&gt;&lt;/DataViewLayoutOptions&gt;
&lt;/template&gt;
&lt;template #footer&gt;
&lt;DataViewLayoutOptions :layout=&quot;layout&quot; @change=&quot;changeMode&quot;&gt;&lt;/DataViewLayoutOptions&gt;
&lt;/template&gt;
</CodeHighlight>
<h3>Paginator</h3>
<p>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 "paginatorLeft" and "paginatorRight" templates.</p>
<CodeHighlight>
<template v-pre>
&lt;DataView :value=&quot;cars&quot; :layout=&quot;layout&quot; paginatorPosition='both' :paginator=&quot;true&quot; :rows=&quot;20&quot;&gt;
&lt;template #paginatorLeft&gt;
&lt;Button type=&quot;button&quot; icon=&quot;pi pi-refresh&quot;/&gt;
&lt;/template&gt;
&lt;template #paginatorRight&gt;
&lt;Button type=&quot;button&quot; icon=&quot;pi pi-search&quot; /&gt;
&lt;/template&gt;
&lt;template #header&gt;
List of Cars
&lt;/template&gt;
&lt;template #listItem=&quot;slotProps&quot; &gt;
&lt;div&gt;Vin: &lt;b&gt;{{slotProps.data.vin}}&lt;/b&gt;&lt;/div&gt;
&lt;/template&gt;
&lt;template #gridItem=&quot;slotProps&quot;&gt;
&lt;div&gt;Vin: &lt;b&gt;{{slotProps.data.vin}}&lt;/b&gt;&lt;/div&gt;
&lt;/template&gt;
&lt;/DataView&gt;
</template>
</CodeHighlight>
<h3>Sorting</h3>
<p>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>
<CodeHighlight>
<template v-pre>
&lt;DataView :value=&quot;cars&quot; :layout=&quot;layout&quot; :sortOrder=&quot;sortOrder&quot; :sortField=&quot;sortField&quot;&gt;
&lt;template #paginatorLeft&gt;
&lt;Button type=&quot;button&quot; icon=&quot;pi pi-refresh&quot;/&gt;
&lt;/template&gt;
&lt;template #paginatorRight&gt;
&lt;Button type=&quot;button&quot; icon=&quot;pi pi-search&quot; /&gt;
&lt;/template&gt;
&lt;template #header&gt;
List of Cars
&lt;/template&gt;
&lt;template #listItem=&quot;slotProps&quot; &gt;
&lt;div&gt;Vin: &lt;b&gt;{{slotProps.data.vin}}&lt;/b&gt;&lt;/div&gt;
&lt;/template&gt;
&lt;template #gridItem=&quot;slotProps&quot;&gt;
&lt;div&gt;Vin: &lt;b&gt;{{slotProps.data.vin}}&lt;/b&gt;&lt;/div&gt;
&lt;/template&gt;
&lt;/DataView&gt;
</template>
</CodeHighlight>
<h3>Properties of DataViewLayoutOptions</h3>
<div class="doc-tablewrapper">
<table class="doc-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Default</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>layout</td>
<td>string</td>
<td>list</td>
<td>Layout of the items, valid values are "list" and "grid".</td>
</tr>
</tbody>
</table>
</div>
<h3>Events of DataViewLayoutOptions</h3>
<div class="doc-tablewrapper">
<table class="doc-table">
<thead>
<tr>
<th>Name</th>
<th>Parameters</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>change</td>
<td>event.originalEvent: browser event <br/>
event.value = layout mode e.g. "list" or "grid"
</td>
<td>Callback to invoke when layout mode is changed.</td>
</tr>
</tbody>
</table>
</div>
<h3>Properties</h3>
<div class="doc-tablewrapper">
<table class="doc-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Default</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>value</td>
<td>array</td>
<td>null</td>
<td>An array of objects to display.</td>
</tr>
<tr>
<td>layout</td>
<td>string</td>
<td>list</td>
<td>Layout of the items, valid values are "list" and "grid".</td>
</tr>
<tr>
<td>rows</td>
<td>number</td>
<td>null</td>
<td>Number of rows to display per page.</td>
</tr>
<tr>
<td>first</td>
<td>number</td>
<td>0</td>
<td>Index of the first record to render.</td>
</tr>
<tr>
<td>totalRecords</td>
<td>number</td>
<td>null</td>
<td>Number of total records, defaults to length of value when not defined.</td>
</tr>
<tr>
<td>paginator</td>
<td>boolean</td>
<td>false</td>
<td>When specified as true, enables the pagination.</td>
</tr>
<tr>
<td>paginatorPosition</td>
<td>string</td>
<td>bottom</td>
<td>Position of the paginator, options are "top","bottom" or "both".</td>
</tr>
<tr>
<td>alwaysShowPaginator</td>
<td>boolean</td>
<td>true</td>
<td>Whether to show it even there is only one page.</td>
</tr>
<tr>
<td>paginatorTemplate</td>
<td>string</td>
<td>FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink RowsPerPageDropdown</td>
<td>Template of the paginator.</td>
</tr>
<tr>
<td>pageLinkSize</td>
<td>number</td>
<td>5</td>
<td>Number of page links to display.</td>
</tr>
<tr>
<td>rowsPerPageOptions</td>
<td>array</td>
<td>null</td>
<td>Array of integer values to display inside rows per page dropdown.</td>
</tr>
<tr>
<td>currentPageReportTemplate</td>
<td>string</td>
<td>({currentPage} of {totalPages})</td>
<td>Template of the current page report element.</td>
</tr>
<tr>
<td>emptyMessage</td>
<td>string</td>
<td>No records found.</td>
<td>Text to display when there is no data.</td>
</tr>
<tr>
<td>sortField</td>
<td>string</td>
<td>null</td>
<td>Name of the field to sort data by default.</td>
</tr>
<tr>
<td>sortOrder</td>
<td>number</td>
<td>null</td>
<td>Order to sort the data by default.</td>
</tr>
<tr>
<td>lazy</td>
<td>boolean</td>
<td>false</td>
<td>Defines if data is loaded and interacted with in lazy manner.</td>
</tr>
</tbody>
</table>
</div>
<h3>Styling</h3>
<p>Following is the list of structural style classes, for theming classes visit <router-link to="/theming">theming</router-link> page.</p>
<div class="doc-tablewrapper">
<table class="doc-table">
<thead>
<tr>
<th>Name</th>
<th>Element</th>
</tr>
</thead>
<tbody>
<tr>
<td>p-dataview</td>
<td>Container element.</td>
</tr>
<tr>
<td>p-dataview-list</td>
<td>Container element in list layout.</td>
</tr>
<tr>
<td>p-dataview-grid</td>
<td>Container element in grid layout.</td>
</tr>
<tr>
<td>p-dataview-header</td>
<td>Header section.</td>
</tr>
<tr>
<td>p-dataview-footer</td>
<td>Footer section.</td>
</tr>
<tr>
<td>p-dataview-content</td>
<td>Container of items.</td>
</tr>
</tbody>
</table>
<h3>Dependencies</h3>
<p>None.</p>
</div>
</TabPanel>
<TabPanel header="Source">
<a href="https://github.com/primefaces/primereact/tree/master/src/showcase/dataview" class="btn-viewsource" target="_blank" rel="noopener noreferrer">
<span>View on GitHub</span>
</a>
<CodeHighlight>
<template v-pre>
&lt;template&gt;
&lt;div&gt;
&lt;div class=&quot;content-section introduction&quot;&gt;
&lt;div class=&quot;feature-intro&quot;&gt;
&lt;h1&gt;DataView&lt;/h1&gt;
&lt;p&gt;DataView displays data in grid or list layout with pagination and sorting features.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;content-section implementation&quot;&gt;
&lt;h3 class=&quot;first&quot;&gt;Default&lt;/h3&gt;
&lt;DataView :value=&quot;cars&quot; :layout=&quot;layout&quot; paginatorPosition='both' :paginator=&quot;true&quot; :rows=&quot;20&quot; :sortOrder=&quot;sortOrder&quot; :sortField=&quot;sortField&quot;&gt;
&lt;template #header&gt;
&lt;div class=&quot;p-grid&quot;&gt;
&lt;div class=&quot;p-col-6&quot; style=&quot;text-align: left&quot;&gt;
&lt;Dropdown v-model=&quot;sortKey&quot; :options=&quot;sortOptions&quot; optionLabel=&quot;label&quot; placeholder=&quot;Sort By&quot; @change=&quot;onSortChange($event)&quot;/&gt;
&lt;/div&gt;
&lt;div class=&quot;p-col-6&quot; style=&quot;text-align: right&quot;&gt;
&lt;DataViewLayoutOptions :layout=&quot;layout&quot; @change=&quot;changeMode&quot;&gt;&lt;/DataViewLayoutOptions&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/template&gt;
&lt;template #listItem=&quot;slotProps&quot; &gt;
&lt;div class=&quot;p-col-12 car-details&quot; style=&quot;padding: 2em; border-bottom: 1px solid #d9d9d9&quot;&gt;
&lt;div class=&quot;p-grid&quot;&gt;
&lt;div class=&quot;p-col-12 p-md-3&quot;&gt;
&lt;img :src=&quot;'/demo/images/car/' + slotProps.data.brand + '.png'&quot; :alt=&quot;slotProps.data.brand&quot;/&gt;
&lt;/div&gt;
&lt;div class=&quot;p-col-12 p-md-8 car-data&quot;&gt;
&lt;div&gt;Vin: &lt;b&gt;{{slotProps.data.vin}}&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;Year: &lt;b&gt;{{slotProps.data.year}}&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;Brand: &lt;b&gt;{{slotProps.data.brand}}&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;Color: &lt;b&gt;{{slotProps.data.color}}&lt;/b&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;p-col-12 p-md-1 search-icon&quot; style=&quot;margin-top: 40px&quot;&gt;
&lt;Button icon=&quot;pi pi-search&quot;&gt;&lt;/Button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/template&gt;
&lt;template #gridItem=&quot;slotProps&quot;&gt;
&lt;div style=&quot;padding: .5em&quot; class=&quot;p-col-12 p-md-3&quot;&gt;
&lt;Panel :header=&quot;slotProps.data.vin&quot; style=&quot;text-align: center&quot;&gt;
&lt;img :src=&quot;'/demo/images/car/' + slotProps.data.brand + '.png'&quot; :alt=&quot;slotProps.data.brand&quot;/&gt;
&lt;div class=&quot;car-detail&quot;&gt;{{slotProps.data.year}} - {{slotProps.data.color}}&lt;/div&gt;
&lt;hr class=&quot;ui-widget-content&quot; style=&quot;border-top: 0&quot; /&gt;
&lt;Button icon=&quot;pi pi-search&quot;&gt;&lt;/Button&gt;
&lt;/Panel&gt;
&lt;/div&gt;
&lt;/template&gt;
&lt;/DataView&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/template&gt;
</template>
</CodeHighlight>
<CodeHighlight lang="javascript">
import CarService from '../../service/CarService';
export default {
data() {
return {
cars: null,
layout: 'list',
sortKey: null,
sortOrder: null,
sortField: null,
sortOptions: [
{label: 'Newest First', value: '!year'},
{label: 'Oldest First', value: 'year'},
{label: 'Brand', value: 'brand'}
]
}
},
carService: null,
created() {
this.carService = new CarService();
},
mounted() {
this.carService.getCarsLarge().then(data => this.cars = data);
},
methods: {
changeMode(event) {
this.layout = event.value;
},
onSortChange(event){
const value = event.value.value;
const sortValue = event.value;
if (value.indexOf('!') === 0) {
this.sortOrder = -1;
this.sortField = value.substring(1, value.length);
this.sortKey = sortValue;
}
else {
this.sortOrder = 1;
this.sortField = value;
this.sortKey = sortValue;
}
}
}
}
</CodeHighlight>
<CodeHighlight lang="css">
.p-dropdown {
width: 12em;
}
</CodeHighlight>
</TabPanel>
</TabView>
</div>
</template>