Balazs Kelemen
Balazs Kelemen

Reputation: 109

unordered list to flexbox

Good afternoon folks,

I have an unordered list that I would like to apply pagination with flexboxes. Any help is highly appreciated:

> <template>
  <div id="app">

  <ul>

    <li v-for="item in items.results" :key="item.id">
        {{ item.pub_date }} {{item.image.file}} {{item.title}}
         <div class="downloads">
          <span
            v-for="downloadable in item.downloadable.filter(d => !!d.document_en)"
            :key="downloadable.id"
           >{{ downloadable.document_en.file }}</span>
           </div>
    </li>
    </ul>

  
  </div>

</template>



<style>

</style>

Upvotes: 0

Views: 128

Answers (2)

Jebasuthan
Jebasuthan

Reputation: 5614

Step 1: Create Pagination.vue component

<template>
  <ul class="pagination">
    <li class="pagination-item">
      <button type="button" @click="onClickFirstPage" :disabled="isInFirstPage">First</button>
    </li>
    <li class="pagination-item">
      <button type="button" @click="onClickPreviousPage" :disabled="isInFirstPage">Previous</button>
    </li>
    <li :key="page.id" v-for="page in pages" class="pagination-item">
      <button type="button" @click="onClickPage(page.name)" :disabled="page.isDisabled"
        :class="{ active: isPageActive(page.name) }">{{ page.name }}</button>
    </li>
    <li class="pagination-item">
      <button type="button" @click="onClickNextPage" :disabled="isInLastPage">Next</button>
    </li>
    <li class="pagination-item">
      <button type="button" @click="onClickLastPage" :disabled="isInLastPage">Last</button>
    </li>
  </ul>
</template>

<script>
export default {
  name: 'pagination',
  props: {
    maxVisibleButtons: {
      type: Number,
      required: false,
      default: 3
    },
    totalPages: {
      type: Number,
      required: true
    },
    perPage: {
      type: Number,
      required: true
    },
    currentPage: {
      type: Number,
      required: true
    }
  },
  computed: {
    isInFirstPage () {
      return this.currentPage === 1
    },
    isInLastPage () {
      if (this.totalPages === 0) {
        return true
      }
      return this.currentPage === this.totalPages
    },
    startPage () {
      // When on the first page
      if (this.currentPage === 1) {
        return 1
      }
      // When on the last page
      if (this.totalPages < this.maxVisibleButtons) {
        return 1
      }
      if (this.currentPage === this.totalPages) {
        return this.totalPages - this.maxVisibleButtons + 1
      }
      // When in between
      return this.currentPage - 1
    },
    endPage () {
      if (this.totalPages === 0) {
        return 1
      }
      if (this.totalPages < this.maxVisibleButtons) {
        return this.totalPages
      }
      return Math.min(this.startPage + this.maxVisibleButtons - 1, this.totalPages)
    },
    pages () {
      const range = []
      for (let i = this.startPage; i <= this.endPage; i+= 1 ) {
        range.push({
          name: i,
          isDisabled: i === this.currentPage 
        })
      }
      return range
    }
  },
  methods: {
    onClickFirstPage () {
      this.$emit('pagechanged', 1)
    },
    onClickPreviousPage () {
      this.$emit('pagechanged', this.currentPage - 1)
    },
    onClickPage (page) {
      this.$emit('pagechanged', page)
    },
    onClickNextPage () {
      this.$emit('pagechanged', this.currentPage + 1)
    },
    onClickLastPage () {
      this.$emit('pagechanged', this.totalPages)
    },
    isPageActive (page) {
      return this.currentPage === page
    }
  }
}
</script>

<style scoped>
  .pagination {
    list-style-type: none;
    float: right;
    margin: 10px 0;
  }
  .pagination-item {
    display: inline-block;
  }
  .active {
    background-color: #943849;
    color: #ffffff !important;
    font-weight: bold;
  }
  button[disabled], html input[disabled] {
    cursor: default;
    color: lightgray;
  }
</style>

Step 2: Add Pagination component reference in app.vue component

import Pagination from './components/Pagination'

Add Pagination component in app.vue

export default {
  components: {
   Pagination,
},

Step 3: Create model data with pagination object

data() {
  return {
    items:[],
    page: 1,
    totalPages: 0,
    totalRecords: 0,
    recordsPerPage: 10
  }
},

Step 4: Create an methods for load data and adding pagination

methods: {
  loadPressRelease () {
    this.showLoader = true
    axios.get(`https://zbeta2.mykuwaitnet.net/backend/en/api/v2/media-center/press-release/?page=${this.page}&page_size=${this.recordsPerPage}&type=5`)
    .then(response => {
      this.showLoader = false
      this.items = response.data
      this.totalPages = Math.ceil(response.data.count / this.recordsPerPage)
      this.totalRecords = response.data.count
    })
  },
  onPageChange(page) {
    this.page = page
    this.loadPressRelease()
  }
}

Step 5: Default page load on created methods

created() {
  this.loadPressRelease()
},

Step 6: HTML template with pagination reference

<div id="app">
    <ul>
      <li v-for="item in items.results" :key="item.id">
        {{ item.pub_date }} {{item.image && item.image.file}} {{item.title}}
        <div class="downloads">
          <span v-for="downloadable in item.downloadable.filter(d => !!d.document_en)"
            :key="downloadable.id">{{ downloadable.document_en.file }}
          </span>
        </div>
      </li>
    </ul>
    <Pagination v-if="items.results" :total-pages="totalPages" :per-page="this.recordsPerPage" :current-page="page" @pagechanged="onPageChange" />
 </div>

DEMO with Loader

Upvotes: 1

Rahul
Rahul

Reputation: 5844

That's pretty much state forward.

Create few constants:

const ROW_PER_PAGE = 10;
const CURRENT_PAGE = 0;

add them in your data method:

return {
 rowPerPage: ROW_PER_PAGE,
 currentPage: CURRENT_PAGE,
 items: allMyData
}

use computed property to return only the required number of rows:

computed: {
 getPaginatedData() {
    const start = this.currentPage * this.rowPerPage;
    const end = start + this.rowPerPage;
    return this.items.slice(start, end); // end index won't be included
 }
}

Now simply use this getPaginatedData in your template

 <li v-for="item in getPaginatedData" :key="item.id">

The last piece is have buttons to change the page. And on each page change, simply update the currentPage var.

For adding pagination buttons, ofcourse you can create your own component, but if you are less on time then you may use per-developed component. The one which I like is https://getbootstrap.com/docs/4.0/components/pagination/

Upvotes: 1

Related Questions