Ra mắt hai series mới cực hot Trí tuệ nhân tạo A đến ZPython công cụ không thể thiếu khi nghiên cứu Data science, Machine learning.

Xây dựng Component phân trang trong Laravel và Vue.js

Vue.js component là một trong những tính năng mạnh mẽ của framework Vue.js, nó giúp mở rộng các thành phần HTML và có khả năng đóng gói cũng như sử dụng lại. Bài viết này sẽ hướng dẫn bạn tạo ra một component cho phép phân trang với các danh sách dữ liệu lớn, sử dụng Laravel 5.4 và Vue 2. Chúng ta cùng bắt đầu nhé.

1. Tạo ứng dụng Laravel

Tạo một ứng dung khung sử dụng Laravel khá nhanh và đơn giản, bạn tham khảo Cài đặt nhanh ứng dụng Laravel. Chú ý, tạo một database và thiết lập kết nối đến database, chạy php artisan migrate để tạo ra sẵn bảng users trong database. Ứng dụng Laravel này chúng ta sẽ tạo ra tên miền ảo cục bộ là http://pagination.dev để dễ dàng thực hiện. Tiếp theo, chúng ta sẽ sử dụng Laravel Tinker tạo ra dữ liệu mẫu bao gồm 100 người dùng.

c:\xampp\htdocs\pagination>php artisan tinker
Psy Shell v0.8.5 (PHP 5.6.20 ΓÇö cli) by Justin Hileman
>>> factory('App\User',100)->create();
...
       App\User {#793
         name: "Roxanne Quitzon",
         email: "willms.carmela@example.org",
         updated_at: "2017-05-21 07:48:36",
         created_at: "2017-05-21 07:48:36",
         id: 98,
       },
       App\User {#794
         name: "Dr. Emie Tillman",
         email: "boyer.della@example.org",
         updated_at: "2017-05-21 07:48:36",
         created_at: "2017-05-21 07:48:36",
         id: 99,
       },
       App\User {#795
         name: "Prof. Katarina Lakin DDS",
         email: "egutmann@example.com",
         updated_at: "2017-05-21 07:48:36",
         created_at: "2017-05-21 07:48:36",
         id: 100,
       },
     ],
   }
>>>

Ok, như vậy chúng ta đã có trong bảng users 100 người dùng để tạo một danh sách có thể phân trang.

2. Tạo API thao tác với dữ liệu

Tạo ra một route trong routers/api.php:

Route::get('/users', 'UserController@index');

Tạo UserController với php artisan make:controller UserController và thêm vào phương thức index() như sau:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\User;

class UserController extends Controller
{
    public function index() {
      $users = User::paginate(5);

      return response()->json($users);
    }
}

Ok, như vậy chúng ta đã thực hiện tạo xong API, thử đăng nhập http://pagination.dev/api/users xem dữ liệu ra đã ổn chưa:

Dữ liệu trả về từ API

3. Tạo trang master Vue.js

Phần backend như vậy đã xong, chúng ta chuyển sang phần fontend sử dụng Vue.js. Trong ứng dụng mẫu Laravel đã có sẵn một ứng dụng mẫu Vue.js, do vậy chúng ta chỉ cần sửa đổi lại resources/assets/js/components/Example.vue:

<template>
    <div class="container">
        <div class="row">
            <div class="col-md-8 col-md-offset-2">
                <div class="panel panel-default">
                    <div class="panel-heading">Ví dụ về Phân trang với Laravel 5.4 và Vue.js 2</div>

                    <div class="panel-body">
                        Hiển thị danh sách người dùng ở đây.
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        data () {
            return {
                users: []
            }
        },
        mounted() {
            axios.get('http://pagination.dev/api/users')
                .then((response) => {
                    this.users = response.data
                })
        }
    }
</script>

Tiếp đến, thiết lập view resources/views/welcome.blade.php là view mặc định của Laravel:

<html lang="vi VN">
    <head>
        <meta charset="utf-8">
        <title>Phân trang trong project Laravel + Vue.js - Allaravel.com</title>

        <!-- Main styles for this application -->
        <link href="{{ mix('css/app.css') }}" rel="stylesheet">
        <meta id="csrf-token" name="csrf-token" value="{{ csrf_token() }}">
    </head>
    <body>
        <div id="app">
             <example></example>
        </div>
        <script src="{{ mix('js/app.js') }}"></script>
    </body>
</html>

Chạy thử và dùng Vue DevTools chúng ta thấy dữ liệu đã được lấy từ API tạo ra ở mục 2.

Lấy dữ liệu từ API thông qua axios

4. Xử lý phân trang trong Vue.js

Từ nãy đến giờ chủ yếu là phần chuẩn bị, bây giờ chúng ta mới đi vào phần chính là tạo ra danh sách người dùng có phân trang. Đầu tiên chúng ta tạo ra User.vue trong resources/assets/js/components để hiển thị từng người dùng:

<template>
  <div class="panel panel-default">
        <div class="panel-heading">
            <h3 class="panel-title" v-text="user.name"></h3>
        </div>
        <div class="panel-body">
            <p v-text="user.email"></p>
        </div>
    </div>
</template>

<script>
  export default {
      props: ['user']
  }
</script>

Tiếp đó, sử dụng component User.vue trong Example.vue để hiển thị danh sách người dùng:

<template>
    <div class="container">
        <div class="row">
            <div class="col-md-8 col-md-offset-2">
                <div class="panel panel-default">
                    <div class="panel-heading">Ví dụ về Phân trang với Laravel 5.4 và Vue.js 2</div>

                    <div class="panel-body">
                        <user v-for="user in users" :user="user" :key="user.id"></user>
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
    import User from './User'
    export default {
        components: { User },
        data () {
            return {
                users: []
            }
        },
        mounted() {
            axios.get('http://pagination.dev/api/users')
                .then((response) => {
                    this.users = response.data.data
                })
        }
    }
</script>

Xem lại http://pagination.dev chúng ta sẽ thấy danh sách người dùng như sau:

Hiển thị danh sách người dùng

Tiếp theo, chúng ta đến phần phân trang, chúng ta tạo ra một component chuyên cho phần phân trang trong resources/assets/js/components/Pagination.vue:

<template>
    <nav>
        <ul class="pagination">
            <li v-if="pagination.current_page > 1">
                <a href="#" aria-label="Previous" v-on:click.prevent="changePage(pagination.current_page - 1)">
                    <span aria-hidden="true">«</span>
                </a>
            </li>
            <li v-for="page in pagesNumber" :class="{'active': page == pagination.current_page}">
                <a href="#" v-on:click.prevent="changePage(page)">{{ page }}</a>
            </li>
            <li v-if="pagination.current_page < pagination.last_page">
                <a href="#" aria-label="Next" v-on:click.prevent="changePage(pagination.current_page + 1)">
                    <span aria-hidden="true">»</span>
                </a>
            </li>
        </ul>
    </nav>
</template>
<script>
    export default{
        props: {
            pagination: {
                type: Object,
                required: true
            },
            offset: {
                type: Number,
                default: 4
            }
        },
        computed: {
            pagesNumber: function () {
                if (!this.pagination.to) {
                    return [];
                }
                var from = this.pagination.current_page - this.offset;
                if (from < 1) {
                    from = 1;
                }
                var to = from + (this.offset * 2);
                if (to >= this.pagination.last_page) {
                    to = this.pagination.last_page;
                }
                var pagesArray = [];
                for (from = 1; from <= to; from++) {
                    pagesArray.push(from);
                }
                return pagesArray;
            }
        },
        methods : {
            changePage: function (page) {
                this.pagination.current_page = page;
            }
        }
    }
</script>

Để sử dụng component này trong Example.vue chúng ta sẽ thay đổi lại mã nguồn chút:

<template>
    <div class="container">
        <div class="row">
            <div class="col-md-8 col-md-offset-2">
                <div class="panel panel-default">
                    <div class="panel-heading">Ví dụ về Phân trang với Laravel 5.4 và Vue.js 2</div>
                    <div class="panel-body">
                        <user v-for="user in users" :user="user" :key="user.id"></user>
                    </div>
                    <pagination v-bind:pagination="pagination" v-on:click.native="getUsers(pagination.current_page)" :offset="4"></pagination>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
    import User from './User'
    import Pagination from './Pagination'
    export default {
        components: { User, Pagination },
        data () {
            return {
                users: [],
                counter: 0,
                pagination: {
                    total: 0,
                    per_page: 2,
                    from: 1,
                    to: 0,
                    current_page: 1
                },
                offset: 4
            }
        },
        mounted() {
            this.getUsers(this.pagination.current_page);
        },
        methods: {
            getUsers (page) {
                axios.get('http://pagination.dev/api/users?page='+page)
                    .then((response) => {
                        this.users = response.data.data
                        this.pagination = response.data
                    })
            }
        }
    }
</script>

Thử lại http://pagination.dev xem phân trang thế nào.

Danh sách người dùng có phân trang

5. Lời kết

Như vậy, chúng ta đã thực hiện xong phần phân trang, nếu bạn muốn style hoặc tạo ra các phân trang riêng thì chúng ta nên xây dựng từ đầu. Nếu bạn muốn sử dụng nhanh một phân trang, chúng ta có thể cài đặt một thư viện phân trang có sẵn ví dụ như:


CÁC BÀI VIẾT KHÁC

FirebirD

Đam mê Toán học, Lập trình. Sở thích chia sẻ kiến thức, Phim hài, Bóng đá, Cà phê sáng với bạn bè.

Xác thực API bằng OAuth 2 với Laravel Passport

Mô phỏng hoạt động của thuộc tính computed trong Vue.js bằng Javascript

0 Bình luận trong "Xây dựng Component phân trang trong Laravel và Vue.js"

Thêm bình luận