isuke
5/23/2015 - 3:08 PM

Vue Simple Pagination

export default
  data: ->
    currentPage: 0
    pageSize: 10
  computed:
    listLength: -> 0 # please override
    pageTotal:  -> Math.ceil(@listLength / @pageSize)
    pageStart:  -> (@currentPage-1)*@pageSize
    pageEnd:    -> (@currentPage*@pageSize)-1
  methods:
    setCurrentPage: (val) ->
      @currentPage = val if 0 < val && val <= @pageTotal
    firstPage: -> @setCurrentPage(1)
    lastPage:  -> @setCurrentPage(@pageTotal)
    prevPage:  -> @setCurrentPage(@currentPage - 1)
    nextPage:  -> @setCurrentPage(@currentPage + 1)
    paginate: (list) -> list.slice(@pageStart, @pageEnd+1)
    fixCurrentPage: ->
      @currentPage = @pageTotal if @pageTotal < @currentPage
      @currentPage = 1          if @currentPage == 0 && @listLength > 0
  watch:
    pageSize:   -> @fixCurrentPage()
    listLength: -> @fixCurrentPage()
<template lang="pug">
ul.pagination
  li.item: a.link.first(@click.prevent="$emit('first-page')") First
  li.item: a.link.prev(@click.prevent="$emit('prev-page')") Prev
  li.item(v-for="i in pageTotal")
    a.link.num(
      @click.prevent="$emit('set-current-page', i)",
      :class="i == currentPage ? '-current' : ''"
    ) {{i}}
  li.item: a.link.next(@click.prevent="$emit('next-page')") Next
  li.item: a.link.last(@click.prevent="$emit('last-page')") Last
</template>

<script lang="coffee">
export default
  props:
    pageTotal:
      type: Number
      required: true
    currentPage:
      type: Number
      required: true
</script>

<style lang="scss" scoped>
.pagination {
  display: inline-flex;
  list-style-type: none;

  > .item {
    &:not(:last-child) {
      margin-right: 0.5em;
    }

    > .link {
      cursor: pointer;
    }

    > .num {
      &.-current {
        color: red;
      }
    }
  }
}
</style>
<template lang="pug">
.sample
  pagination(
    :page-total="pageTotal",
    :current-page="currentPage",
    @first-page="firstPage",
    @prev-page="prevPage",
    @set-current-page="setCurrentPage($event)",
    @next-page="nextPage",
    @last-page="lastPage",
  )

  ul
    li(v-for="user in paginate(users)", :key="user.id") {{ user.id }}
</template>

<script lang="coffee">
import paginationable from '@/scripts/mixins/paginationable.coffee'

import Pagination from '@/components/Pagination.vue'

export default
  mixins: [paginationable]
  components:
    'pagination': Pagination
  data: ->
    users: []
  computed:
    listLength: -> @users.length
  compiled: ->
    axios.get "/users.json"
    .then (response)=>
      @users = response.data
      @currentPage = 1
    .catch (response)=>
      console.log response
</script>

<style lang="scss" scoped>
.sample {
}
</style>