Refactored Paginator to make two-way binding optional

pull/12/head
cagataycivici 2019-05-24 00:18:15 +03:00
parent cfe1be241a
commit 423b8ecc0e
11 changed files with 160 additions and 176 deletions

View File

@ -365,7 +365,7 @@ export default {
'p-dropdown-label p-inputtext', 'p-dropdown-label p-inputtext',
{ {
'p-placeholder': this.label === null && this.placeholder, 'p-placeholder': this.label === null && this.placeholder,
'p-dropdown-label-empty': !this.placeholder 'p-dropdown-label-empty': (this.label == null || this.label.length === 0)
} }
]; ];
}, },

View File

@ -1,21 +1,14 @@
<template> <template>
<button :class="containerClass" @click="$emit('click',$event)"> <button :class="containerClass" v-on="$listeners">
<span class="p-paginator-icon pi pi-step-backward"></span> <span class="p-paginator-icon pi pi-step-backward"></span>
</button> </button>
</template> </template>
<script> <script>
export default { export default {
inheritAttrs: false,
props: {
disabled: {
type: null,
default: false
}
},
computed: { computed: {
containerClass() { containerClass() {
return ['p-paginator-first p-paginator-element p-link', { return ['p-paginator-first p-paginator-element p-link', {
'p-disabled': this.disabled 'p-disabled': this.$attrs.disabled
}]; }];
} }
} }

View File

@ -1,21 +1,15 @@
<template> <template>
<button :class="containerClass" @click="$emit('click',$event)"> <button :class="containerClass" v-on="$listeners">
<span class="p-paginator-icon pi pi-step-forward"></span> <span class="p-paginator-icon pi pi-step-forward"></span>
</button> </button>
</template> </template>
<script> <script>
export default { export default {
inheritAttrs: false,
props: {
disabled: {
type: null,
default: false
}
},
computed: { computed: {
containerClass() { containerClass() {
return ['p-paginator-last p-paginator-element p-link', { return ['p-paginator-last p-paginator-element p-link', {
'p-disabled': this.disabled 'p-disabled': this.$attrs.disabled
}]; }];
} }
} }

View File

@ -1,21 +1,14 @@
<template> <template>
<button :class="containerClass" @click="$emit('click',$event)"> <button :class="containerClass" v-on="$listeners">
<span class="p-paginator-icon pi pi-caret-right"></span> <span class="p-paginator-icon pi pi-caret-right"></span>
</button> </button>
</template> </template>
<script> <script>
export default { export default {
inheritAttrs: false,
props: {
disabled: {
type: null,
default: false
}
},
computed: { computed: {
containerClass() { containerClass() {
return ['p-paginator-next p-paginator-element p-link', { return ['p-paginator-next p-paginator-element p-link', {
'p-disabled': this.disabled 'p-disabled': this.$attrs.disabled
}]; }];
} }
} }

View File

@ -1,3 +1,9 @@
<template>
<span class="p-paginator-pages">
<button v-for="pageLink of value" :key="pageLink" :class="['p-paginator-page p-paginator-element p-link', {'p-highlight': ((pageLink - 1) === page)}]"
@click="onPageLinkClick($event, pageLink)">{{pageLink}}</button>
</span>
</template>
<script> <script>
export default { export default {
inheritAttrs: false, inheritAttrs: false,
@ -12,18 +18,6 @@
value: pageLink value: pageLink
}); });
} }
},
render() {
return (
<span class="p-paginator-pages">
{
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>
);
} }
} }
</script> </script>

View File

@ -37,7 +37,8 @@
text-decoration: none; text-decoration: none;
vertical-align: middle; vertical-align: middle;
text-align: center; text-align: center;
position: relative; position: relative;
cursor: pointer;
} }
.p-paginator .p-paginator-pages { .p-paginator .p-paginator-pages {
@ -80,7 +81,7 @@
-webkit-box-shadow: none; -webkit-box-shadow: none;
} }
.p-paginator a.p-disabled { .p-paginator .p-disabled {
outline: 0 none; outline: 0 none;
} }

View File

@ -3,14 +3,14 @@
<div class="p-paginator-left-content" v-if="$scopedSlots.left"> <div class="p-paginator-left-content" v-if="$scopedSlots.left">
<slot name="left" :state="currentState"></slot> <slot name="left" :state="currentState"></slot>
</div> </div>
<template v-for="(item,i) of templateItems"> <template v-for="item of templateItems">
<FirstPageLink v-if="item === 'FirstPageLink'" :key="i" @click="changePageToFirst($event)" :disabled="isFirstPage" /> <FirstPageLink v-if="item === 'FirstPageLink'" :key="item" @click="changePageToFirst($event)" :disabled="isFirstPage" />
<PrevPageLink v-else-if="item === 'PrevPageLink'" :key="i" @click="changePageToPrev($event)" :disabled="isFirstPage" /> <PrevPageLink v-else-if="item === 'PrevPageLink'" :key="item" @click="changePageToPrev($event)" :disabled="isFirstPage" />
<NextPageLink v-else-if="item === 'NextPageLink'" :key="i" @click="changePageToNext($event)" :disabled="isLastPage" /> <NextPageLink v-else-if="item === 'NextPageLink'" :key="item" @click="changePageToNext($event)" :disabled="isLastPage" />
<LastPageLink v-else-if="item === 'LastPageLink'" :key="i" @click="changePageToLast($event)" :disabled="isLastPage" /> <LastPageLink v-else-if="item === 'LastPageLink'" :key="item" @click="changePageToLast($event)" :disabled="isLastPage" />
<PageLinks v-else-if="item === 'PageLinks'" :key="i" :value="updatePageLinks" :page="page" @click="pageLinkClick($event)" /> <PageLinks v-else-if="item === 'PageLinks'" :key="item" :value="pageLinks" :page="page" @click="changePageLink($event)" />
<CurrentPageReport v-else-if="item === 'CurrentPageReport'" :key="i" :template="currentPageReportTemplate" :page="page" :pageCount="pageCount" /> <CurrentPageReport v-else-if="item === 'CurrentPageReport'" :key="item" :template="currentPageReportTemplate" :page="page" :pageCount="pageCount" />
<RowsPerPageDropdown v-else-if="item === 'RowsPerPageDropdown'" :key="i" :value="rows" :options="rowsPerPageOptions" @rowsChange="rowsChange($event)" /> <RowsPerPageDropdown v-else-if="item === 'RowsPerPageDropdown' && rowsPerPageOptions" :key="item" :rows="d_rows" :options="rowsPerPageOptions" @rows-change="onRowChange($event)" />
</template> </template>
<div class="p-paginator-right-content" v-if="$scopedSlots.right"> <div class="p-paginator-right-content" v-if="$scopedSlots.right">
<slot name="right" :state="currentState"></slot> <slot name="right" :state="currentState"></slot>
@ -58,14 +58,68 @@ export default {
default: '({currentPage} of {totalPages})' default: '({currentPage} of {totalPages})'
} }
}, },
components: { data() {
'CurrentPageReport': CurrrentPageReport, return {
'FirstPageLink': FirstPageLink, d_first: this.first,
'LastPageLink': LastPageLink, d_rows: this.rows
'NextPageLink': NextPageLink, }
'PageLinks': PageLinks, },
'PrevPageLink': PrevPageLink, watch: {
'RowsPerPageDropdown': RowsPerPageDropdown, first(newValue) {
this.d_first = newValue;
},
rows(newValue) {
this.d_rows = newValue;
}
},
methods: {
changePage(p) {
const pc = this.pageCount;
if (p >= 0 && p < pc) {
this.d_first = this.d_rows * p;
const state = {
page: p,
first: this.d_first,
rows: this.d_rows,
pageCount: pc
};
this.$emit('update:first', this.d_first);
this.$emit('update:rows', this.d_rows);
this.$emit('page-change', state);
}
},
changePageToFirst(event) {
if(!this.isFirstPage) {
this.changePage(0);
}
event.preventDefault();
},
changePageToPrev(event) {
this.changePage(this.page - 1);
event.preventDefault();
},
changePageLink(event) {
this.changePage(event.value - 1);
event.originalEvent.preventDefault();
},
changePageToNext(event) {
this.changePage(this.page + 1);
event.preventDefault();
},
changePageToLast(event) {
if(!this.isLastPage) {
this.changePage(this.pageCount - 1);
}
event.preventDefault();
},
onRowChange(value) {
this.d_rows = value;
this.changePage(this.page);
}
}, },
computed: { computed: {
templateItems() { templateItems() {
@ -76,10 +130,10 @@ export default {
return keys; return keys;
}, },
page() { page() {
return Math.floor(this.first / this.rows); return Math.floor(this.d_first / this.d_rows);
}, },
pageCount() { pageCount() {
return Math.ceil(this.totalRecords / this.rows) || 1; return Math.ceil(this.totalRecords / this.d_rows) || 1;
}, },
isFirstPage() { isFirstPage() {
return this.page === 0; return this.page === 0;
@ -88,24 +142,24 @@ export default {
return this.page === this.pageCount - 1; return this.page === this.pageCount - 1;
}, },
calculatePageLinkBoundaries() { calculatePageLinkBoundaries() {
var numberOfPages = this.pageCount; const numberOfPages = this.pageCount;
var visiblePages = Math.min(this.pageLinkSize, numberOfPages); const visiblePages = Math.min(this.pageLinkSize, numberOfPages);
//calculate range, keep current in middle if necessary //calculate range, keep current in middle if necessary
var start = Math.max(0, Math.ceil(this.page - ((visiblePages) / 2))); let start = Math.max(0, Math.ceil(this.page - ((visiblePages) / 2)));
var end = Math.min(numberOfPages - 1, start + visiblePages - 1); let end = Math.min(numberOfPages - 1, start + visiblePages - 1);
//check when approaching to last page //check when approaching to last page
var delta = this.pageLinkSize - (end - start + 1); const delta = this.pageLinkSize - (end - start + 1);
start = Math.max(0, start - delta); start = Math.max(0, start - delta);
return [start, end]; return [start, end];
}, },
updatePageLinks() { pageLinks() {
var pageLinks = []; let pageLinks = [];
var boundaries = this.calculatePageLinkBoundaries; let boundaries = this.calculatePageLinkBoundaries;
var start = boundaries[0]; let start = boundaries[0];
var end = boundaries[1]; let end = boundaries[1];
for(var i = start; i <= end; i++) { for(var i = start; i <= end; i++) {
pageLinks.push(i + 1); pageLinks.push(i + 1);
@ -116,51 +170,19 @@ export default {
currentState() { currentState() {
return { return {
page: this.page, page: this.page,
first: this.first, first: this.d_first,
rows: this.rows rows: this.d_rows
} }
} }
}, },
methods: { components: {
changePage(first, rows) { 'CurrentPageReport': CurrrentPageReport,
const pc = this.pageCount; 'FirstPageLink': FirstPageLink,
const p = Math.floor(first / rows); 'LastPageLink': LastPageLink,
'NextPageLink': NextPageLink,
if (p >= 0 && p < pc) { 'PageLinks': PageLinks,
let newPageState = { 'PrevPageLink': PrevPageLink,
first: first, 'RowsPerPageDropdown': RowsPerPageDropdown,
rows: rows, },
page: p,
pageCount: pc
};
this.$emit('page-change', newPageState);
this.$emit('update:first', first);
this.$emit('update:rows', rows);
}
},
changePageToFirst(event) {
this.changePage(0, this.rows);
event.preventDefault();
},
changePageToPrev(event) {
this.changePage(this.first - this.rows, this.rows);
event.preventDefault();
},
pageLinkClick(event) {
this.changePage((event.value - 1) * this.rows, this.rows);
},
changePageToNext(event) {
this.changePage(this.first + this.rows, this.rows);
event.preventDefault();
},
changePageToLast(event) {
this.changePage((this.pageCount - 1) * this.rows, this.rows);
event.preventDefault();
},
rowsChange(event) {
this.changePage(0, event.value.code);
}
}
} }
</script> </script>

View File

@ -1,21 +1,14 @@
<template> <template>
<button :class="containerClass" @click="$emit('click',$event)"> <button :class="containerClass" v-on="$listeners">
<span class="p-paginator-icon pi pi-caret-left"></span> <span class="p-paginator-icon pi pi-caret-left"></span>
</button> </button>
</template> </template>
<script> <script>
export default { export default {
inheritAttrs: false,
props: {
disabled: {
type: null,
default: false
}
},
computed: { computed: {
containerClass() { containerClass() {
return ['p-paginator-prev p-paginator-element p-link', { return ['p-paginator-prev p-paginator-element p-link', {
'p-disabled': this.disabled 'p-disabled': this.$attrs.disabled
}]; }];
} }
} }

View File

@ -1,27 +1,28 @@
<template> <template>
<Dropdown v-model="selectedRow" :options="rowOptions" optionLabel="name" @change="$emit('rowsChange',$event)" :placeholder="String(value)"></Dropdown> <Dropdown :value="rows" :options="rowsOptions" optionLabel="label" optionValue="value"
@input="onChange($event)"></Dropdown>
</template> </template>
<script> <script>
export default { export default {
inheritAttrs: false, inheritAttrs: false,
props: { props: {
options: Array, options: Array,
value: Number rows: Number
}, },
data() { methods: {
return { onChange(value) {
selectedRow: null this.$emit('rows-change', value);
} }
}, },
computed: { computed: {
rowOptions() { rowsOptions() {
var newOption = [] let opts = [];
if(this.options) { if (this.options) {
for(var i= 0; i<this.options.length; i++) { for(let i= 0; i < this.options.length; i++) {
newOption.push({name: String(this.options[i]), code: this.options[i]}) opts.push({label: String(this.options[i]), value: this.options[i]})
} }
} }
return newOption; return opts;
} }
} }

View File

@ -8,11 +8,12 @@
</div> </div>
<div class="content-section implementation"> <div class="content-section implementation">
<h3 class="first">Default</h3> <h3>Basic</h3>
<Paginator :first.sync="first" :rows.sync="rows" :totalRecords="totalRecords" :rowsPerPageOptions="[10,20,30]"></Paginator> <Paginator :rows="10" :totalRecords="totalRecords" :rowsPerPageOptions="[10,20,30]"></Paginator>
<h3>Custom Template</h3> <h3>Custom</h3>
<Paginator :first.sync="first2" :rows="1" :totalRecords="totalRecords2" @page-change="onPageChangeCustom($event)" template="FirstPageLink PrevPageLink CurrentPageReport NextPageLink LastPageLink"> <Paginator :first.sync="first" :rows="1" :totalRecords="totalRecords2"
template="FirstPageLink PrevPageLink CurrentPageReport NextPageLink LastPageLink">
<template #left> <template #left>
<Button type="button" icon="pi pi-refresh" @click="reset()"/> <Button type="button" icon="pi pi-refresh" @click="reset()"/>
</template> </template>
@ -37,20 +38,18 @@ export default {
data() { data() {
return { return {
first: 0, first: 0,
rows: 10, totalRecords: 120,
totalRecords: 50, totalRecords2: 12
first2: 0,
totalRecords2: 12,
image: 'nature1'
} }
}, },
methods: { methods: {
onPageChangeCustom(event) {
this.image = 'nature' + (event.page + 1);
},
reset() { reset() {
this.first2 = 0; this.first = 0;
this.image = 'nature1'; }
},
computed: {
image() {
return 'nature' + (this.first + 1);
} }
}, },
components: { components: {
@ -60,12 +59,12 @@ export default {
</script> </script>
<style scoped> <style scoped>
.p-button.p-button-icon-only { .p-button.p-button-icon-only {
border-radius: 0; border-radius: 0;
} }
.image-gallery { .image-gallery {
text-align: center; text-align: center;
padding: 1em; padding: 1em;
} }
</style> </style>

View File

@ -229,11 +229,12 @@ onPage(event) {
&lt;/div&gt; &lt;/div&gt;
&lt;div class="content-section implementation"&gt; &lt;div class="content-section implementation"&gt;
&lt;h3 class="first"&gt;Default&lt;/h3&gt; &lt;h3&gt;Basic&lt;/h3&gt;
&lt;Paginator :first.sync="first" :rows.sync="rows" :totalRecords="totalRecords" :rowsPerPageOptions="[10,20,30]"&gt;&lt;/Paginator&gt; &lt;Paginator :rows="10" :totalRecords="totalRecords" :rowsPerPageOptions="[10,20,30]"&gt;&lt;/Paginator&gt;
&lt;h3&gt;Custom Template&lt;/h3&gt; &lt;h3&gt;Custom&lt;/h3&gt;
&lt;Paginator :first.sync="first2" :rows="1" :totalRecords="totalRecords2" @page-change="onPageChangeCustom($event)" template="FirstPageLink PrevPageLink CurrentPageReport NextPageLink LastPageLink"&gt; &lt;Paginator :first.sync="first" :rows="1" :totalRecords="totalRecords2"
template="FirstPageLink PrevPageLink CurrentPageReport NextPageLink LastPageLink"&gt;
&lt;template #left&gt; &lt;template #left&gt;
&lt;Button type="button" icon="pi pi-refresh" @click="reset()"/&gt; &lt;Button type="button" icon="pi pi-refresh" @click="reset()"/&gt;
&lt;/template&gt; &lt;/template&gt;
@ -243,7 +244,7 @@ onPage(event) {
&lt;/Paginator&gt; &lt;/Paginator&gt;
&lt;div class="image-gallery"&gt; &lt;div class="image-gallery"&gt;
&lt;img :src="&#39;demo/images/nature/&#39; + image + &#39;.jpg&#39;" /&gt; &lt;img :src="'demo/images/nature/' + image + '.jpg'" /&gt;
&lt;/div&gt; &lt;/div&gt;
&lt;/div&gt; &lt;/div&gt;
@ -253,30 +254,23 @@ onPage(event) {
</CodeHighlight> </CodeHighlight>
<CodeHighlight lang="javascript"> <CodeHighlight lang="javascript">
import PaginatorDoc from './PaginatorDoc';
export default { export default {
data() { data() {
return { return {
first: 0, first: 0,
rows: 10, totalRecords: 120,
totalRecords: 50, totalRecords2: 12
first2: 0,
totalRecords2: 12,
image: 'nature1'
} }
}, },
methods: { methods: {
onPageChangeCustom(event) {
this.image = 'nature' + (event.page + 1);
},
reset() { reset() {
this.first2 = 0; this.first = 0;
this.image = 'nature1';
} }
}, },
components: { computed: {
'PaginatorDoc': PaginatorDoc image() {
return 'nature' + (this.first + 1);
}
} }
} }
</CodeHighlight> </CodeHighlight>