import { Vue, Component, Prop, Watch } from 'vue-property-decorator'; /** * Pagination for the table */ @Component({ name: 'paginator', }) export default class Paginator extends Vue { /** * Total number of items */ @Prop({ type: Number, required: true }) readonly numberOfItems!: number; /** * Number of items per page */ @Prop({ type: Number, default: 10 }) readonly itemsPerPage!: number; /** * Offset (skip) */ @Prop({ type: Number, default: 0 }) readonly skip!: number; /** * Enable mobile mode or not: one item per page */ @Prop({ type: Boolean, default: false }) readonly mobileModeEnabled!: boolean; /** * Internal state of the component */ state: {[key: string]: any} = { firstPage: 1, currentPage: 1, lastPage: 1, finalItemsPerPage: this.mobileModeEnabled ? 1 : this.itemsPerPage, }; /** * Method called when a click on a page is triggered * The methods emits a page-change event with the new offset and the new page * @param page Destination page */ goto(page: number) { const { lastPage, finalItemsPerPage } = this.state; if (page < 1 || page > lastPage) { return; } this.state.currentPage = page; const newSkip = (page * finalItemsPerPage) - finalItemsPerPage; this.$emit('page-change', newSkip, page); } /** * Watch the changes on [[Paginator.numberOfItems]] and react accordingly * @param newNumber The new number of items */ @Watch('numberOfItems') onNumberOfItemsChanged(newNumber: number) { const { finalItemsPerPage } = this.state; this.state.lastPage = Math.ceil(newNumber / finalItemsPerPage); } /** * Watch the changes on [[Paginator.skip]] and react accordingly * @param newSkip The new offset */ @Watch('skip') onSkipChanged(newSkip: number) { const { finalItemsPerPage } = this.state; this.state.currentPage = (newSkip + finalItemsPerPage) / finalItemsPerPage; } /** * Watch the changes on [[Paginator.mobileModeEnabled]] and react accordingly * @param newMobileMode The new mode */ @Watch('mobileModeEnabled') onMobileModeEnabledChanged(newMobileMode: boolean) { if (newMobileMode) { this.state.finalItemsPerPage = 1; } else { this.state.finalItemsPerPage = this.itemsPerPage; } } /** * Watch the changes on [[Paginator.itemsPerPage]] and react accordingly * @param newItemsPerPage The new number of items per page */ @Watch('itemsPerPage') onItemsPerPageChanged(newItemsPerPage: number) { if (this.mobileModeEnabled) { this.state.finalItemsPerPage = 1; } else { this.state.finalItemsPerPage = newItemsPerPage; } } /** * Called when the component is mounted */ mounted() { const { finalItemsPerPage } = this.state; this.state.lastPage = Math.ceil(this.numberOfItems / finalItemsPerPage); this.state.currentPage = (this.skip + finalItemsPerPage) / finalItemsPerPage; } }