【问题标题】:How can I add pagination in listing page using vue js and laravel?如何使用 vue js 和 laravel 在列表页面中添加分页?
【发布时间】:2016-07-02 14:25:18
【问题描述】:

我有一个使用 vue js 和 laravel 的列表页面。在此页面中还包括过滤和排序功能。目前列出、排序和过滤工作正常。我需要在此列表页面中包含分页。我不知道如何包含这个我的客户需要这个。我在vue js方面没有太多经验。我当前的代码如下。您能否检查并帮助我整合分页?

版本为 vue js(1.0.25) 和 laravel(5.2)

dashboard.blade.php

@extends('layouts.app')

@section('title', 'Dashboard')

@section('style')
    <style>
        th.active .arrow {
            opacity: 1;
        }

        .arrow {
            display: inline-block;
            vertical-align: middle;
            width: 0;
            height: 0;
            margin-left: 5px;
            opacity: 0.66;
        }

        .arrow.asc {
            border-left: 4px solid transparent;
            border-right: 4px solid transparent;
            border-bottom: 4px solid #42b983;
        }

        .arrow.dsc {
            border-left: 4px solid transparent;
            border-right: 4px solid transparent;
            border-top: 4px solid #42b983;
        }

        #search {
            margin-bottom: 10px;
        }
    </style>
@endsection

@section('content')
    <div class="container">
        <div class="row">
            <h1 class="page-header">{{ trans('messages.customerListPageHeadingLabel') }}</h1>
            <template id="grid-template">
                <table class="table table-hover table-bordered">
                    <thead>
                    <tr>
                        <th v-for="key in columns" @click="sortBy(key)" :class="{active: sortKey == key}">@{{ heading[key] }} <span class="arrow" :class="sortOrders[key] > 0 ? 'asc' : 'dsc'"></span>
                        </th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr v-for="(index, customer) in customers | filterBy filterKey | orderBy sortKey sortOrders[sortKey]">
                        <td>@{{ customer.erp_id }}</td>
                        <td>@{{customer.firstname}}</td>
                        <td><a href="{{ url('/customer/details/') }}/@{{ customer.id }}">@{{customer.lastname}}</a></td>
                        <td>@{{customer.email}}</td>
                        <td>@{{customer.phone_1}}</td>
                        <td>@{{customer.status}}</td>
                        <td>@{{customer.created_on}}</td>
                    </tr>
                    </tbody>
                </table>
            </template>
            <div id="app">
                <div class="form-group col-md-4">
                    <form id="search" class="form-inline">
                        <label for="query">{{ trans('messages.customerListPageSearchBox') }} </label>
                        <input name="query" class="form-control" v-model="searchQuery">
                    </form>
                </div>
                <br>
                <customer-grid  :customers="{{$listCustomers}}"  :columns="gridColumns" :heading="colTitles"  :filter-key="searchQuery"></customer-grid>
            </div>
        </div>
    </div>
    @endsection

    @push('script')
            <!-- Vue Js -->
    <script src="/assets/js/vue.js"></script>
    <script src="/assets/js/vue-resource.js"></script>
    <script>
        Vue.component('customer-grid', {
            template: '#grid-template',
            props: {
                customers: Array,
                columns: Array,
                filterKey: String,
                heading:Object
            },

            data: function () {
                var sortOrders = {}
                this.columns.forEach(function (key) {
                    sortOrders[key] = 1
                })
                return {
                    sortKey: '',
                    sortOrders: sortOrders
                }
            },
            methods: {
                sortBy: function (key) {
                    this.sortKey = key
                    this.sortOrders[key] = this.sortOrders[key] * -1
                }
            }
        })

        // bootstrap the demo
        var demo = new Vue({
            el: '#app',
            data: {
                searchQuery: '',
                gridColumns: ['erp_id', 'firstname', 'lastname', 'email', 'phone_1', 'status', 'created_on'],
                gridData: null,
                colTitles: {'erp_id':'@lang('messages.customerListPageTableCustomerNo')', 'firstname':'@lang('messages.customerListPageTableFirstname')', 'lastname':'@lang('messages.customerListPageTableLastname')', 'email':'E-Mail', 'phone_1':'@lang('messages.customerListPageTablePhone')', 'status':'Status', 'created_on':'@lang('messages.customerListPageTableAddedDate')'}
            },

            created: function() {
                this.fetchData()
            },

            methods: {
                fetchData: function () {
                    var self = this;
                    $.get('/', function( data ) {
                        self.gridData = data;
                    });
                }
            }
        });
    </script>
    @endpush

routes.php

Route::get('/', ['as' => 'listCustomersPage', 'uses' => 'CustomerController@index']);

CustomerController.php

public function index()
    {
        $listCustomers    = Customer::select('id', 'erp_id', 'firstname', 'lastname', 'email', 'phone_1', 'status', DB::raw("DATE_FORMAT(created_at, '%d.%m.%Y %H:%i') AS created_on"))
            ->orderBy('id', 'desc')
            ->get();
        return view('dashboard', compact('listCustomers'));
        /*return view('dashboard');*/
    }

【问题讨论】:

    标签: php laravel vue.js


    【解决方案1】:

    在 Vue 中如何使用 Laravel 分页的示例:

    控制器:

    class UserController extends Controller
        {
            public function index()
            {
                return view('user.index', [
                    'users' => User::all()->paginate(25),
                ]);
            }
        }
    

    查看:

    <div id="app">
        <tr v-for="user in users">
        ... do something here with the user ... 
        <tr>
    </div>
    

    Vue:

       new Vue({
                el: '#app',
                data: {
                    users: {!! collect($users->items())->toJson() !!}
                },
            });
    

    【讨论】:

      【解决方案2】:

      我已经用 vue.js 编写了自己的分页(我也使用 Vue 和 laravel),因为 vue.js 没有开箱即用的分页。 我构建了这个组件:

      <style>
          li.page-item {
              cursor: pointer;
          }
          li.active_pagination a {
              background-color: #1c84c6 !important;
              border-color: #1c84c6 !important;
              color: #ffffff !important;
          }
      </style>
      
      <template>
          <div>
              <ul class="pagination pull-right">
                  <li class="page-item" :class="{'disabled': currentPage == 1}">
                      <a class="page-link" href="#" @click.prevent="changeCurrentPage(1)" aria-label="Previous">
                          <span aria-hidden="true">&laquo;</span>
                          <span class="sr-only">Previous</span>
                      </a>
                  </li>
                  <li class="page-item" :class="{'disabled': currentPage == 1}">
                      <a class="page-link" href="#" @click.prevent="decrementCurrentPage(currentPage)" aria-label="Previous">
                          <span aria-hidden="true">&lsaquo;</span>
                          <span class="sr-only">Previous</span>
                      </a>
                  </li>
      
                  <li v-for="index in indexes" class="page-item" :class="{'active_pagination': currentPage == index}"><a class="page-link" @click.prevent="changeCurrentPage(index)">{{index}}</a></li>
      
                  <li class="page-item" :class="{'disabled': currentPage == totalPages}">
                      <a class="page-link" href="#" @click.prevent="incrementCurrentPage(currentPage)" aria-label="Next">
                          <span aria-hidden="true">&rsaquo;</span>
                          <span class="sr-only">Next</span>
                      </a>
                  </li>
                  <li class="page-item" :class="{'disabled': currentPage == totalPages}">
                      <a class="page-link" href="#" @click.prevent="changeCurrentPage(totalPages)" aria-label="Next">
                          <span aria-hidden="true">&raquo;</span>
                          <span class="sr-only">Next</span>
                      </a>
                  </li>
              </ul>
          </div>
      </template>
      
      <script>
      
          module.exports = {
      
              props: ['currentPage','totalPages', 'totalShownIndexes'],
      
              computed:  {
      
                  indexes: function() {
                      var temp_pageIndexes = [];
      
                      if (this.totalPages > 1) {
                          if (this.totalPages <= this.totalShownIndexes) {
                              for (var i = 1; i <= this.totalPages; i++) {
                                  if (temp_pageIndexes.indexOf(i) == -1) {
                                      temp_pageIndexes.push(i);
                                  }
                              }
                          }
                          else {
                              var sigma = Math.ceil((this.totalShownIndexes - 1) / 2);
      
                              if (sigma + this.currentPage >= this.totalPages) {
                                  var temp_right = (this.totalPages - this.currentPage);
                                  var temp_left = this.currentPage - (sigma + (sigma - temp_right));
      
                                  temp_pageIndexes.push('...');
                                  for (var i = temp_left; i <= this.totalPages; i++) {
                                      temp_pageIndexes.push(i);
                                  }
                              }
                              else if (this.currentPage - sigma <= 1) {
                                  var temp_left = sigma - this.currentPage;
                                  var temp_right = sigma + (this.currentPage + sigma + temp_left);
      
                                  for (var i = 1; i <= temp_right - 1; i++) {
                                      temp_pageIndexes.push(i);
                                  }
                                  temp_pageIndexes.push('...');
                              }
                              else {
                                  for (var i = this.currentPage - sigma; i <= this.currentPage + sigma; i++) {
                                      temp_pageIndexes.push(i);
                                  }
                                  temp_pageIndexes.push('...');
                              }
                          }
                          return temp_pageIndexes;
                      }
                      else {
                          this.currentPage = 1;
                          this.totalPages = 1;
                          return ['1'];
                      }
                  }
              },
      
              methods: {
                  changeCurrentPage(newCurrentPage) {
                      console.log('newCurrentPage: ' + newCurrentPage);
                      if(newCurrentPage > 0 && newCurrentPage < this.totalPages + 1 && newCurrentPage != this.currentPage && newCurrentPage != '...') {
                          this.currentPage = newCurrentPage;
                          this.$parent.pagination.currentPage = this.currentPage;
                      }
                  },
      
                  incrementCurrentPage(currentPage) {
                      this.changeCurrentPage(Number(currentPage) + 1);
                  },
      
                  decrementCurrentPage(currentPage) {
                      this.changeCurrentPage(Number(currentPage) - 1)
                  }
              }
          }
      </script>
      

      我构建了这个过滤器:

      Vue.filter('paginate', function (list, currentPage, perPage) {
      
          var totalPages = Math.ceil(list.length / perPage);
      
          if(totalPages == 0) {
              totalPages = 1;
          }
          this.pagination.totalPages = totalPages;
      
          var index = (currentPage - 1) * perPage;
      
          return list.slice(index, index + perPage);
      });
      

      您可以将此过滤器放在过滤/排序列表的末尾,如下所示:

      v-for="(index, customer) in customers | filterBy filterKey | orderBy sortKey sortOrders[sortKey] | paginate pagination.currentPage pagination.perPage"
      

      为此,您需要在数据对象中添加一个分页对象,如下所示:

      data() {
          return {
              pagination: {
                  options: [200,100,50,25,10,1],
                  perPage: 10,
                  totalPages: 1,
                  currentPage: 1,
                  totalShownIndexes: 5
              }
          }
      }
      

      options 属性是可选的。我用它来填充一个带有 perPage 选择的组合框。因此,您可以选择每页显示多少项目。选择更改后,您将设置 perPage 属性。

      现在你差不多完成了。您唯一需要的是这些方法:

      changePerPage(perPage) {
          this.pagination.perPage = perPage;
          this.resetCurrentPage();
      },
      
      resetCurrentPage() {
          this.pagination.currentPage = 1;
      }
      

      changePerPage() 方法仅在您想要具有每页选择的组合框时才需要。

      只要应用其他过滤器,就应该调用resetCurrentPage() 方法。这就是你需要做的。

      我希望你会发现这很有用。

      【讨论】:

      • AM 试图遵循代码,但在 vue 中是新手,这似乎有点令人困惑。您介意通过准确标记模板文件中的内容来编辑答案吗?
      【解决方案3】:

      分页可以在您雄辩的选择语句中完成,您现在要做的就是在刀片上设置其外观样式编辑客户控制器的内容,如下所示

      public function index()
      {
          $list = Customer::select('id', 'erp_id', 'firstname', 'lastname', 'email', 'phone_1', 'status', DB::raw("DATE_FORMAT(created_at, '%d.%m.%Y %H:%i') AS created_on"))
              ->orderBy('id', 'desc')
              ->get();
          $all = count($list);
          $listCustomers = Customer::select('id', 'erp_id', 'firstname',   'lastname', 'email', 'phone_1', 'status', DB::raw("DATE_FORMAT(created_at, '%d.%m.%Y %H:%i') AS created_on"))
              ->orderBy('id', 'desc')
              ->paginate(10);//note here that im assuming you want to display 10 results per page 
          return view('dashboard', compact('listCustomers', 'all'));
          /*return view('dashboard');*/
      }
      

      在您的仪表板刀片上添加将指定不同页面的 div

      @section('title', 'Dashboard')
      
      @section('style')
      <style>
          th.active .arrow {
              opacity: 1;
          }
      
          .arrow {
              display: inline-block;
              vertical-align: middle;
              width: 0;
              height: 0;
              margin-left: 5px;
              opacity: 0.66;
          }
      
          .arrow.asc {
              border-left: 4px solid transparent;
              border-right: 4px solid transparent;
              border-bottom: 4px solid #42b983;
          }
      
          .arrow.dsc {
              border-left: 4px solid transparent;
              border-right: 4px solid transparent;
              border-top: 4px solid #42b983;
          }
      
          #search {
              margin-bottom: 10px;
          }
      </style>
      @endsection
      
      @section('content')
      <div class="container">
          <div class="row">
              <h1 class="page-header">{{     trans('messages.customerListPageHeadingLabel') }}</h1>
              <template id="grid-template">
                  <table class="table table-hover table-bordered">
                      <thead>
                      <tr>
                          <th v-for="key in columns" @click="sortBy(key)" :class="{active: sortKey == key}">@{{ heading[key] }} <span class="arrow" :class="sortOrders[key] > 0 ? 'asc' : 'dsc'"></span>
                          </th>
                      </tr>
                      </thead>
                      <tbody>
                      <tr v-for="(index, customer) in customers | filterBy filterKey | orderBy sortKey sortOrders[sortKey]">
                          <td>@{{ customer.erp_id }}</td>
                          <td>@{{customer.firstname}}</td>
                          <td><a href="{{ url('/customer/details/') }}/@{{ customer.id }}">@{{customer.lastname}}</a></td>
                          <td>@{{customer.email}}</td>
                          <td>@{{customer.phone_1}}</td>
                          <td>@{{customer.status}}</td>
                          <td>@{{customer.created_on}}</td>
                      </tr>
                      </tbody>
                  </table>
                  <div class="w100 categoryFooter"><!--I added this-->
                       <div class="pagination pull-left no-margin-top">
                       {!! $listCustomers->links(null, ['class' => 'pagination no-margin-top']) !!}
                  </div>
                  <div class="pull-right pull-right col-sm-4 col-xs-12 no-padding text-right text-left-xs">
                  <p>Showing 1-10 of {{ $all }} results</p>
                  </div>
                              </div>
              </template>
              <div id="app">
                  <div class="form-group col-md-4">
                      <form id="search" class="form-inline">
                          <label for="query">{{ trans('messages.customerListPageSearchBox') }} </label>
                          <input name="query" class="form-control" v-model="searchQuery">
                      </form>
                  </div>
                  <br>
                  <customer-grid  :customers="{{$listCustomers}}"  :columns="gridColumns" :heading="colTitles"  :filter-key="searchQuery"></customer-grid>
              </div>
          </div>
      </div>
      @endsection
      
      @push('script')
              <!-- Vue Js -->
      <script src="/assets/js/vue.js"></script>
      <script src="/assets/js/vue-resource.js"></script>
      <script>
          Vue.component('customer-grid', {
              template: '#grid-template',
              props: {
                  customers: Array,
                  columns: Array,
                  filterKey: String,
                  heading:Object
              },
      
              data: function () {
                  var sortOrders = {}
                  this.columns.forEach(function (key) {
                      sortOrders[key] = 1
                  })
                  return {
                      sortKey: '',
                      sortOrders: sortOrders
                  }
              },
              methods: {
                  sortBy: function (key) {
                      this.sortKey = key
                      this.sortOrders[key] = this.sortOrders[key] * -1
                  }
              }
          })
      
          // bootstrap the demo
          var demo = new Vue({
              el: '#app',
              data: {
                  searchQuery: '',
                  gridColumns: ['erp_id', 'firstname', 'lastname', 'email', 'phone_1', 'status', 'created_on'],
                  gridData: null,
                  colTitles: {'erp_id':'@lang('messages.customerListPageTableCustomerNo')', 'firstname':'@lang('messages.customerListPageTableFirstname')', 'lastname':'@lang('messages.customerListPageTableLastname')', 'email':'E-Mail', 'phone_1':'@lang('messages.customerListPageTablePhone')', 'status':'Status', 'created_on':'@lang('messages.customerListPageTableAddedDate')'}
              },
      
              created: function() {
                  this.fetchData()
              },
      
              methods: {
                  fetchData: function () {
                      var self = this;
                      $.get('/', function( data ) {
                          self.gridData = data;
                      });
                  }
              }
          });
      </script>
      @endpush
      

      确保将值 10 更改为 {{ $count }} 变量以指定每页显示多少结果。请注意,它很可能是 10,这是您的最大值,除了最后一页。祝你好运

      【讨论】:

        猜你喜欢
        • 2019-09-28
        • 2021-06-07
        • 2020-08-10
        • 1970-01-01
        • 1970-01-01
        • 2019-05-31
        • 1970-01-01
        • 2020-01-15
        • 2018-04-08
        相关资源
        最近更新 更多