0

api.php

Route::get('/products', 'ProductsController@index');

Query:

$products = DB::table('sizes')
  ->join('products', 'sizes.id', '=', 'products.sizes')
  ->join('categories', 'products.category', '=', 'categories.id')
  ->select('products.*', 'categories.catname', 'categories.catimage', 'categories.catdescription', 'sizes.size')
  ->where([['products.is_active', '=', 1],['categories.is_active', '=', 1],])
  ->orderBy('products.id', 'ASC')
   ->paginate(5);
return $products;

Vue component:

<div v-for="product in products.data" :key="product.id">
      <h1>{{ product.name }}</h1>
    </div>
    <pagination :data="products" @pagination-change-page="getResults"></pagination>

methods: {
  getResults(page = 1) {
    this.$url.get('products/results?page=' + page)
    .then(response => {
    console.log(response)
    this.products = response.data;
    });
  }
}

The initial load of products works, it shows 5 products and shows pagination. Whenever I try to click a new page from the pagination, I end up with multiple errors.

CORS(which I don't see how since my app is completely public) and two network errors

from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource

net::ERR_FAILED

Uncaught (in promise) Error: Network Error

Is there something I'm missing here? Am I supposed to make another endpoint that handles pagination or should this be handled from the same exact endpoint where it fetches initial pagination?

Mike Shiv
  • 203
  • 4
  • 12

1 Answers1

1

1. Copy and paste this code in a new component, like 'Pagination.vue'

<template>
   <nav aria-label="...">
       <ul class="pagination justify-content-center">
           <li class="page-item" :class="{ disabled: pagination.current_page <= 1 }">
               <a style="cursor:pointer" class="page-link" @click.prevent="changePage(1)"  >First page</a>
           </li>
           <li class="page-item" :class="{ disabled: pagination.current_page <= 1 }">
               <a style="cursor:pointer" class="page-link" @click.prevent="changePage(pagination.current_page - 1)"><i class="fa fa-arrow-left"></i></a>
           </li>

           <li class="page-item" v-for="(page,index) in pages"  :key="page" :class="isCurrentPage(page) ? 'active' : ''">
               <a style="cursor:pointer" class="page-link" @click.prevent="changePage(page)">{{ page }}
                   <span v-if="isCurrentPage(page)" class="sr-only">(current)</span>
               </a>
           </li>

           <li class="page-item" :class="{ disabled: pagination.current_page >= pagination.last_page }">
               <a style="cursor:pointer" class="page-link" @click.prevent="changePage(pagination.current_page + 1)"><i class="fa fa-arrow-right"></i></a>
           </li>
           <li class="page-item" :class="{ disabled: pagination.current_page >= pagination.last_page }">
               <a style="cursor:pointer" class="page-link" @click.prevent="changePage(pagination.last_page)">Last Page</a>
           </li>
       </ul>
   </nav>
</template>

<script>
   export default {
       props:['pagination', 'offset'],
       methods: {
           isCurrentPage(page){
               return this.pagination.current_page === page
           },
           changePage(page) {
               if (page > this.pagination.last_page) {
                   page = this.pagination.last_page;
               }
               this.pagination.current_page = page;
               this.$emit('paginate');
           }
       },
       computed: {
           pages() {
               let pages = []

               let from = this.pagination.current_page - Math.floor(this.offset / 2)

               if (from < 1) {
                   from = 1
               }

               let to = from + this.offset -1

               if (to > this.pagination.last_page) {
                   to = this.pagination.last_page
               }

               while (from <= to) {
                   pages.push(from)
                   from++
               }

               return pages
           }
       }
   }
</script>

2. Make it global in your js/app.js file,

Vue.component('pagination', require('./components/Pagination.vue').default);

3. In the vue component, below to the data, set the pagination component like this, you can cange the offset as much you can

<pagination v-if="pagination.last_page > 1" 
  :pagination="pagination" 
  :offset="7" 
  @paginate="getItems()">
</pagination>

4. Set current page to 1,

data(){
   return{
      items: [],
         pagination: {
            current_page: 1,
         },
   }
},

5. Make a method to send the page number and collect paginated data,

getItems(){
    axios.get('api/items?page='+this.pagination.current_page)
        .then(response => {
            this.items = response.data.data;
            this.pagination = response.data.meta;
        });
},

6. Make sure you return data paginated data with resource collection,

public function index(){
    return new GeneralCollection(Item::with('category')->orderBy('name')->paginate(10));
}

***if you, don't have the collection file, make one , like 'GeneralCollection',

php artisan make:resource GeneralCollection

then, include it on the controllers where you want to return collected data,

use App\Http\Resources\GeneralCollection;

7. Congrats !

SAKIB
  • 475
  • 5
  • 7