Paginator for DataTable

pull/12/head
cagataycivici 2019-06-29 14:29:19 +03:00
parent 793b2276af
commit 6f20655a74
5 changed files with 368 additions and 175 deletions

View File

@ -2,9 +2,18 @@
<div class="p-datatable p-component">
<slot></slot>
<div class="p-datatable-wrapper">
<div class="p-datatable-header" v-if="$scopedSlots.header">
<div class="p-datatable-header" v-if="$slots.header">
<slot name="header"></slot>
</div>
<DTPaginator v-if="paginatorTop" :rows="rows" :first="first" :totalRecords="totalRecordsLength" :pageLinkSize="pageLinkSize" :template="paginatorTemplate" :rowsPerPageOptions="rowsPerPageOptions"
:currentPageReportTemplate="currentPageReportTemplate" :class="{'p-paginator-top': paginatorTop}" @page="onPage($event)">
<template #left v-if="$scopedSlots.paginatorLeft">
<slot name="paginatorLeft"></slot>
</template>
<template #right v-if="$scopedSlots.paginatorRight">
<slot name="paginatorRight"></slot>
</template>
</DTPaginator>
<table>
<thead class="p-datatable-thead">
<tr>
@ -14,7 +23,7 @@
</tr>
</thead>
<tbody class="p-datatable-tbody">
<tr class="p-datatable-row" v-for="(rowData, index) of value" :key="getRowKey(rowData, index)">
<tr class="p-datatable-row" v-for="(rowData, index) of data" :key="getRowKey(rowData, index)">
<td v-for="(col,i) of columns" :key="col.columnKey||col.field||i" :style="col.bodyStyle" :class="col.bodyClass">
<ColumnSlot :data="rowData" :column="col" type="body" v-if="col.$scopedSlots.body" />
<template v-else>{{resolveFieldData(rowData, col.field)}}</template>
@ -22,12 +31,25 @@
</tr>
</tbody>
</table>
<DTPaginator v-if="paginatorBottom" :rows="rows" :first="first" :totalRecords="totalRecordsLength" :pageLinkSize="pageLinkSize" :template="paginatorTemplate" :rowsPerPageOptions="rowsPerPageOptions"
:currentPageReportTemplate="currentPageReportTemplate" :class="{'p-paginator-bottom': paginatorBottom}" @page="onPage($event)">
<template #left v-if="$scopedSlots.paginatorLeft">
<slot name="paginatorLeft"></slot>
</template>
<template #right v-if="$scopedSlots.paginatorRight">
<slot name="paginatorRight"></slot>
</template>
</DTPaginator>
<div class="p-datatable-footer" v-if="$slots.footer">
<slot name="footer"></slot>
</div>
</div>
</div>
</template>
<script>
import ObjectUtils from '../utils/ObjectUtils';
import Paginator from '../paginator/Paginator';
const ColumnSlot = {
functional: true,
@ -63,13 +85,67 @@ export default {
dataKey: {
type: String,
default: null
},
rows: {
type: Number,
default: 0
},
first: {
type: Number,
default: 0
},
totalRecords: {
type: Number,
default: 0
},
paginator: {
type: Boolean,
default: false
},
paginatorPosition: {
type: String,
default: 'bottom'
},
alwaysShowPaginator: {
type: Boolean,
default: true
},
paginatorTemplate: {
type: String,
default: 'FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink RowsPerPageDropdown'
},
pageLinkSize: {
type: Number,
default: 5
},
rowsPerPageOptions: {
type: Array,
default: null
},
currentPageReportTemplate: {
type: String,
default: '({currentPage} of {totalPages})'
},
lazy: {
type: Boolean,
default: false
}
},
data() {
return {
columns: []
columns: [],
d_first: this.first,
d_rows: this.rows
};
},
watch: {
first(newValue) {
this.d_first = newValue;
},
rows(newValue) {
this.d_rows = newValue;
}
},
mounted() {
this.columns = [...this.$children];
},
@ -79,10 +155,65 @@ export default {
},
resolveFieldData(rowData, field) {
return ObjectUtils.resolveFieldData(rowData, field);
},
onPage(event) {
this.d_first = event.first;
this.d_rows = event.rows;
this.$emit('update:first', this.d_first);
this.$emit('update:rows', this.d_rows);
this.$emit('page', event);
}
},
computed: {
data() {
if (this.value && this.value.length) {
let data = this.value;
/*if (data && data.length && this.sortField) {
data = this.sort();
}*/
if (this.paginator) {
const first = this.lazy ? 0 : this.d_first;
return data.slice(first, first + this.d_rows);
}
else {
return data;
}
}
else {
return null;
}
},
totalRecordsLength() {
if (this.totalRecords)
return this.totalRecords;
else
return this.value ? this.value.length : 0;
},
empty() {
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;
},
},
components: {
'ColumnSlot': ColumnSlot
'ColumnSlot': ColumnSlot,
'DTPaginator': Paginator
}
}
</script>

View File

@ -3,7 +3,7 @@
<div class="p-dataview-header" v-if="$scopedSlots.header">
<slot name="header"></slot>
</div>
<Paginator v-if="paginatorTop" :rows="rows" :first="first" :totalRecords="getTotalRecords" :pageLinkSize="pageLinkSize" :template="paginatorTemplate" :rowsPerPageOptions="rowsPerPageOptions"
<DVPaginator v-if="paginatorTop" :rows="rows" :first="first" :totalRecords="getTotalRecords" :pageLinkSize="pageLinkSize" :template="paginatorTemplate" :rowsPerPageOptions="rowsPerPageOptions"
:currentPageReportTemplate="currentPageReportTemplate" :class="{'p-paginator-top': paginatorTop}" @page="onPage($event)">
<template #left v-if="$scopedSlots.paginatorLeft">
<slot name="paginatorLeft"></slot>
@ -11,7 +11,7 @@
<template #right v-if="$scopedSlots.paginatorRight">
<slot name="paginatorRight"></slot>
</template>
</Paginator>
</DVPaginator>
<div class="p-dataview-content">
<div class="p-grid">
<template v-for="(item,index) of items">
@ -21,7 +21,7 @@
<div v-if="isEmpty" class="p-col-12">{{emptyMessage}}</div>
</div>
</div>
<Paginator v-if="paginatorBottom" :rows="rows" :first="first" :totalRecords="getTotalRecords" :pageLinkSize="pageLinkSize" :template="paginatorTemplate" :rowsPerPageOptions="rowsPerPageOptions"
<DVPaginator v-if="paginatorBottom" :rows="rows" :first="first" :totalRecords="getTotalRecords" :pageLinkSize="pageLinkSize" :template="paginatorTemplate" :rowsPerPageOptions="rowsPerPageOptions"
:currentPageReportTemplate="currentPageReportTemplate" :class="{'p-paginator-bottom': paginatorBottom}" @page="onPage($event)">
<template #left v-if="$scopedSlots.paginatorLeft">
<slot name="paginatorLeft"></slot>
@ -29,188 +29,193 @@
<template #right v-if="$scopedSlots.paginatorRight">
<slot name="paginatorRight"></slot>
</template>
</Paginator>
</DVPaginator>
<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: 0
},
first: {
type: Number,
default: 0
},
totalRecords: {
type: Number,
default: 0
},
paginator: {
type: Boolean,
default: false
},
paginatorPosition: {
type: String,
default: 'bottom'
},
alwaysShowPaginator: {
type: Boolean,
default: true
},
paginatorTemplate: {
type: String,
default: 'FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink RowsPerPageDropdown'
},
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
}
import ObjectUtils from '../utils/ObjectUtils';
import Paginator from '../paginator/Paginator';
export default {
props: {
value: {
type: Array,
default: null
},
data() {
return {
d_first: this.first,
d_rows: this.rows
layout: {
type: String,
default: 'list'
},
rows: {
type: Number,
default: 0
},
first: {
type: Number,
default: 0
},
totalRecords: {
type: Number,
default: 0
},
paginator: {
type: Boolean,
default: false
},
paginatorPosition: {
type: String,
default: 'bottom'
},
alwaysShowPaginator: {
type: Boolean,
default: true
},
paginatorTemplate: {
type: String,
default: 'FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink RowsPerPageDropdown'
},
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 {
d_first: this.first,
d_rows: this.rows
}
},
watch: {
first(newValue) {
this.d_first = newValue;
},
rows(newValue) {
this.d_rows = newValue;
}
},
methods: {
onPage(event) {
this.d_first = event.first;
this.d_rows = event.rows;
this.$emit('update:first', this.d_first);
this.$emit('update:rows', this.d_rows);
this.$emit('page', event);
},
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;
}
},
watch: {
first(newValue) {
this.d_first = newValue;
},
rows(newValue) {
this.d_rows = newValue;
else {
return null;
}
}
},
computed: {
containerClass() {
return ['p-dataview p-component', {
'p-dataview-list': (this.layout === 'list'),
'p-dataview-grid': (this.layout === 'grid')
}
]
},
methods: {
onPage(event) {
this.d_first = event.first;
this.d_rows = event.rows;
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;
},
items() {
if (this.value && this.value.length) {
let data = this.value;
this.$emit('update:first', this.d_first);
this.$emit('update:rows', this.d_rows);
this.$emit('page', event);
},
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;
},
items() {
if (this.value && this.value.length) {
let data = this.value;
if (data && data.length && this.sortField) {
data = this.sort();
}
if (this.paginator) {
const first = this.lazy ? 0 : this.d_first;
return data.slice(first, first + this.d_rows);
}
else {
return data;
}
if (data && data.length && this.sortField) {
data = this.sort();
}
if (this.paginator) {
const first = this.lazy ? 0 : this.d_first;
return data.slice(first, first + this.d_rows);
}
else {
return null;
return data;
}
}
}
}
else {
return null;
}
}
},
components: {
'DVPaginator': Paginator
}
}
</script>
<style>

View File

@ -115,6 +115,11 @@ export default new Router({
path: '/datatable/templating',
name: 'datatabletemplating',
component: () => import('./views/datatable/DataTableTemplatingDemo.vue')
},
{
path: '/datatable/paginator',
name: 'datatablepaginator',
component: () => import('./views/datatable/DataTablePaginatorDemo.vue')
},
{
path: '/dataview',

View File

@ -0,0 +1,44 @@
<template>
<div>
<DataTableSubMenu />
<div class="content-section introduction">
<div class="feature-intro">
<h1>DataTable - Paginator</h1>
<p>Pagination is enabled by setting paginator property to true and defining the rows attribute as the number of rows per page.</p>
</div>
</div>
<div class="content-section implementation">
<DataTable :value="cars" :paginator="true" :rows="10">
<Column field="vin" header="Vin"></Column>
<Column field="year" header="Year"></Column>
<Column field="brand" header="Brand"></Column>
<Column field="color" header="Color"></Column>
</DataTable>
</div>
</div>
</template>
<script>
import CarService from '../../service/CarService';
import DataTableSubMenu from './DataTableSubMenu';
export default {
data() {
return {
cars: null
}
},
carService: null,
created() {
this.carService = new CarService();
},
mounted() {
this.carService.getCarsLarge().then(data => this.cars = data);
},
components: {
'DataTableSubMenu': DataTableSubMenu
}
}
</script>

View File

@ -11,6 +11,12 @@
<div class="content-section implementation">
<DataTable :value="cars">
<template #header>
<div style="line-height:1.87em" class="clearfix">
<Button icon="pi pi-refresh" style="float: right"/>
List of Cars
</div>
</template>
<Column field="vin" header="Vin"></Column>
<Column field="year" header="Year"></Column>
<Column field="brand" header="Brand">
@ -25,6 +31,9 @@
<Button type="button" icon="pi pi-pencil" class="p-button-warning"></Button>
</template>
</Column>
<template #footer>
In total there are {{cars.length}} cars.
</template>
</DataTable>
</div>
</div>
@ -37,7 +46,6 @@ import DataTableSubMenu from './DataTableSubMenu';
export default {
data() {
return {
columns: null,
cars: null
}
},