Work Laravel 5.3 + Vue.JS 1.0 - Pagination + Sort

Laravel 5.3 + Vue.JS 1.0 - Pagination + Sort

15th Sep, 2016 | Work

Following on from Laravel 5.3 + Vue.Js 1.0 - Create/Read, let us now add pagination as well as sort functionality. The end result will be a frontend pagination/sort functionality that plays nicely with our backend system so that every interactivity involves the backend.
Starting with this post, all the code will also be available on Github tagged with the title of the corresponding post so it is easier to follow. I have to add, though, that I am new to Vue.JS having been OK at AngularJS; I'm also back to Laravel after a bit of time off tinkering with God-forsaken Wordpress.

Alright, let's code.

In the last post, we already had our Laravel Controller/Model set up to do the pagination and order-by. So they are all good to go. The only changes therefore would be on the frontend.
The end result is:

In the screenshot, we are on page two and the current sort is name, descending (Z - A). All work will go inside our MailingList.vue component:

  1. The data function is extended to include some necessary initialisations for the pagination and sort:
data: function() {
    return {
        newMList: { name: ''},
        mLists: [],
        orderToggle: 1,
        orderAttr: 'name',
        pagination: {
            total: 0,
            per_page: 10,
            current_page: 1,
            last_page: 0,
            from: 1,
            to: 10
        }
    }
}
  1. The template repeater has additional parameters in the v-for to facilitate sort:
<tr v-for="mList in mLists | orderBy orderAttr orderToggle">
    <td>{{ mList.name }}</td>
    <td>{{ mList.created_at }}</td>
    <td>{{ mList.updated_at }}</td>
</tr>
  1. The template has sort buttons next to each column name - these will call a function onClick and their icons will change as appropriate
<tr>
    <th>Name <button @click="changeSort('name')"><i class="fa {{ getSortIcon('name') }}"></i></button></th>
    <th>Created <button @click="changeSort('created_at')"><i class="fa {{ getSortIcon('created_at') }}"></i></button></th>
    <th>Updated <button @click="changeSort('updated_at')"><i class="fa {{ getSortIcon('updated_at') }}"></i></button></th>
</tr>
  1. There are two new methods: changeSort() and getSortIcon() - these are responsible for changing the order of sort and the sort icon. Notice in the screenshot that the current sort column (name) has a specific font-awesome icon which will point up/down depending on the sort order. The other columns just maintain the default sort icon.
  2. The changeSort() method checks the existing value of the sort attribute and the sort order, toggles the order and calls the fetchMLists() method with necessary parameters. The fetchMLists() method queries Laravel for the new data and upon returning it, sets the sort order/attribute in the scope to the new values the user supplied upon clicking any of the sort buttons.
changeSort: function(attr) {
    var orderToggle = ( this.orderAttr == attr ) ? this.orderToggle * -1 : 1;
    this.fetchMLists(attr, orderToggle);
}
fetchMLists: function (orderAttr, orderToggle) {
    var orderBy = orderAttr ? orderAttr : this.orderAttr;
    var order = orderToggle ? orderToggle : this.orderToggle;
    var progress = this.$Progress;
    var mLists = [];

    let params = {
        perPage: this.pagination.per_page,
        page: this.pagination.current_page,
        orderBy: orderBy,
        order: ( order == 1 ) ? 'asc' : 'desc'
    };
    this.$http.get(this.resourceUrl, {params : params}).then(function(response) {
        if ( response.data && response.data.data && response.data.data.length ) {
            this.$set('mLists', response.data.data);
            this.orderAttr = orderBy;
            this.orderToggle = order;

            var pagination = {
                total: response.data.total,
                per_page: response.data.per_page,
                current_page: response.data.current_page,
                last_page: response.data.last_page,
                from: response.data.from,
                to: response.data.to
            };
            this.$set('pagination', pagination);
        }
    }, function(error) {
        swal('An Error Occurred', 'Please refresh the page and try again.', 'error');
    });
}

 

PS: the swal() methods come in from the sweetalert component that just makes alerts a little bit nicer - this will be included on the Github repo.


You will notice progress.() methods in the Github code as well that come from another component - out of scope for this post.

And that's it.
When the user clicks on a page number in the pagination, the application will call the fetchMLists() method after updating the scope values for the pagination. The fetchMLists() method will always use current page number and records per page parameters (which are initalised in the data function) when querying Laravel. These values are updated dynamically and so everything is wired nicely. When Laravel responds, it also sets the pagination data accordingly.

Have fun playing with it - Github repository this way.

Comments