0
votes

I am learning to paginate data returned from an API using AXIOS. I have a working set of code, but there is a place in the code defined by bootstrap for :Total-rows, this is currently hardcoded but this creates extra rows based on the value rather than a computed value. I want to calculate the number of rows dynamically.

I know that I can count the response data from the api using: this.variable = response.data.length, but the way I am calling the data is using page variable to paginate.

Any suggestions on an efficient way to accomplish this somewhat seemingly simple call?

<template>
  <div id="app">
    <div class="row">
      <div class="col-md-12">
        <li v-for="item in todos" :key="item.id">
          {{ item.name }} : {{ item.type }}
        </li>   
      </div>
    </div>
    <b-pagination size="md" :total-rows="54" v-model="currentPage" :per-page="10" @input="getPostData(currentPage)">
    </b-pagination>
  </div>    
</template>

VUE

<script>
//Import axios for REST API calls
import axios from 'axios'
import 'regenerator-runtime/runtime';
//Import bootstrap CSS
import 'bootstrap/dist/css/bootstrap.css'
//Import bootstrap vue CSS
import 'bootstrap-vue/dist/bootstrap-vue.css'

const baseURL = 'http://localhost:3000/todos?_page='+this.currentPage+'&_limit='+this.limit;

export default {
  name: 'app',
  data () {
    return {
      title: 'Vue.js Pagination Example With Bootstrap',
      currentPage: 1,
      limit: 5,
      todos: [],
       todoName: "",
      todoType: "",
    }
  },
  methods: {
    // Fetches todos when the component is created.
    getPostData (currentPage) {
      axios.get('http://localhost:3000/todos?_page='+this.currentPage+'&_limit='+this.limit)
      .then(response => {
        //console.log(response)
        // JSON responses are automatically parsed.
        this.todos = response.data
         
      })
      .catch(e => {
        this.errors.push(e)
      })
    },
    
       async addTodo() {
      const res = await axios.post(baseURL, {
        name: this.todoName,
        type: this.todoType,
      });
      this.todos = [...this.todos, res.data];
      //resets the input field
      this.todoName = "";
      this.todoType = "";
    },
   
  }, //end of methods
 //detects the current page on load
   mounted(currentPage){
    this.getPostData(currentPage)
  } 
}
</script>
1

1 Answers

0
votes

You will need the API to return the total amount of rows, otherwise your frontend have no way of knowing how many pages to show.

You can find an example of this below, which use a dummy/testing API called reqres. This API returns various information, like the current page, total amount of rows and per page and of course the data for the requested page.

new Vue({
  el: "#app",
  data() {
    return {
      currentPage: 1,
      totalRows: 0,
      perPage: 0,
      users: [],
      request: null
    }
  },
  methods: {
    async getData(page) {
      const response = await fetch(`https://reqres.in/api/users?page=${page}&per_page=3`).then(resp => resp.json())
      this.perPage = response.per_page;
      this.users = response.data;
      this.totalRows = response.total;

      // Only for testing purposes
      this.request = response
    }
  },
  created() {
    this.getData(this.currentPage)
  }
})
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/bootstrap-vue/2.18.1/bootstrap-vue.min.css" />

<script src="//cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/bootstrap-vue/2.18.1/bootstrap-vue.min.js"></script>

<div id="app">
  <b-pagination 
        v-model="currentPage" 
      :total-rows="totalRows" 
      :per-page="perPage" 
      @change="getData">
  </b-pagination>
  <ul>
    <li v-for="{ first_name, last_name } in users">
      {{ first_name }} {{ last_name }}
    </li>
  </ul>
  Request
  <pre>{{ request }}</pre>
</div>