I'm looking at upgrading to v3 and was disappointed to see inline-template has been removed. Therefore I'm trying to convert to use a scoped slot instead.
I have defined the following list component:
<template>
<slot :items="filteredItems" :page="page" :totalPages="totalPages" :onPageChanged="onPageChanged"></slot>
</template>
<script>
export default {
props: {
items: {
type: Array
},
initialPage: {
type: Number,
default: 1,
},
pageSize: {
type: Number,
default: 10
}
},
beforeCreate() {
this.page = this.initialPage;
},
computed: {
filteredItems() {
return this.items.slice((this.page - 1) * this.pageSize, this.page * this.pageSize);
},
totalPages() {
return Math.ceil(this.items.length / this.pageSize);
}
},
methods: {
onPageChanged(page) {
console.log('Page changed!!!');
this.page = page;
}
}
};
</script>
Which is called like so:
<list :items="[ { foo: 'A' }, { foo: 'B' }, { foo: 'C' } ]" :page-size="2" #="{ items, page, totalPages, onPageChanged }">
<ul class="list-group">
<li class="list-group-item" v-for="item in items">{{ item.foo }}</li>
</ul>
<pager :page="page" :total-pages="totalPages" @pageChanged="onPageChanged"></pager>
</list>
Here's the pager component:
<template>
<ul class="pagination">
<li class="page-item" v-if="hasPreviousPage"><a href="#" @click="changePage(1)" class="page-link">«</a></li>
<li class="page-item" v-if="hasPreviousPage"><a href="#" @click="changePage(page - 1)" class="page-link">‹</a></li>
<li v-for="page in pages" :class="['page-item', { active: page.isActive }]"><a href="#" @click="changePage(page.name)" class="page-link">{{ page.name }}</a></li>
<li class="page-item disabled" v-if="page < totalPages - 2"><span class="page-link"> ... </span></li>
<li class="page-item" v-if="page < totalPages - 2"><a href="#" @click="changePage(totalPages)" class="page-link">{{ totalPages }}</a></li>
<li class="page-item" v-if="hasNextPage"><a href="#" @click="changePage(page + 1)" class="page-link">›</a></li>
<li class="page-item" v-if="hasNextPage"><a href="#" @click="changePage(totalPages)" class="page-link">»</a></li>
</ul>
</template>
<script>
export default {
props: {
page: {
type: Number,
required: true
},
totalPages: {
type: Number,
required: true
}
},
computed: {
hasPreviousPage() {
return this.page > 1;
},
hasNextPage() {
return this.page < this.totalPages;
},
pages() {
const range = [];
for (let i = this.page <= 2 ? 1 : this.page - 2; i <= (this.page >= this.totalPages - 2 ? this.totalPages : this.page + 2); i++) {
range.push({
name: i,
isActive: this.page == i
});
}
return range;
}
},
methods: {
changePage(page, e = event) {
e.preventDefault();
// Trigger the page changed event.
this.$emit('pageChanged', page);
}
}
};
</script>
However whenever I try to change the page, the changePage
method is invoked which emits the pageChanged
event, but it doesn't invoke the onPageChanged
method within the list component.
I'd appreciate if someone could show me what I'm doing wrong. Thanks
The event name should be written in
kebab-case
format as follows :and use it like
@page-changed="onPageChanged