Laravel 5 and Vue JS SimpleCRUD with Pagination example



 Most popular JS Framework are Angular JS, Vue JS, and ReactJs. Angular JS and Vue JS are a very user-friendly JS Framework and most popular. It provides to manage whole project or application without refresh page and powerful jquery validation.
In this post, I going to learn how to Simple BookCrud application with pagination using Laravel 5.

In this example I added "Book Management" with you can do several options like as below:

1. Book Listing

2. Book Create

3. Book Edit

4. Book Delete


Step 1: Laravel Installation


In first step, If you haven't installed Laravel in your system then you have to run bellow command and get fresh Laravel project.

composer create-project --prefer-dist laravel/laravel BookCrud

Step 2: Create books table and model


In this step we have to create migration for books table using Laravel 5 php artisan command, so first fire bellow command:

php artisan make:migration create_books_table

After this command, you will find one file in following path database/migrations and you have to put below code in your migration file for creating books table.

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;


class CreateBooksTable extends Migration
{


    public function up()
    {
        Schema::create('books', function (Blueprint $table) {
            $table->increments('id');
            $table->string('title')->nullable();
            $table->text('description')->nullable();
            $table->string('author')->nullable();
            $table->timestamps();
        });
    }


    public function down()
    {
        Schema::drop("books");
    }
}

After create "books" table you should create Book model for books, so first create a file in this path app/Book.php and put bellow content in book.php file:

app/Book.php

namespace App;


use Illuminate\Database\Eloquent\Model;


class Book extends Model
{


    public $fillable = ['title','description'];


}


Step 3: Add Route and Controller


Now we have to add the route for books CRUD and pagination, in this example, i added resource route and one for manage-vue for application, if we add resource route then it will add the index, create, edit and delete route automatically. So add bellow line in your route file.

app/Http/routes.php

Route::get('manage-vue', 'VueBookController@manageVue');
Route::resource('vuebooks','VueBookController');
Ok, now we should create new controller as VueBookController in this path app/Http/Controllers/VueBookController.php. this controller will manage all route method:

app/Http/Controllers/VueBookController.php

namespace App\Http\Controllers;


use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Book;


class VueBookController extends Controller
{


    public function manageVue()
    {
        return view('manage-vue');
    }


    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index(Request $request)
    {
        $books = Book::latest()->paginate(5);


        $response = [
            'pagination' => [
                'total' => $books->total(),
                'per_page' => $books->perPage(),
                'current_page' => $books->currentPage(),
                'last_page' => $books->lastPage(),
                'from' => $books->firstBook(),
                'to' => $books->lastBook()
            ],
            'data' => $books
        ];


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


    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $this->validate($request, [
            'title' => 'required',
            'description' => 'required',
        ]);


        $create = Book::create($request->all());


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


    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, $id)
    {
        $this->validate($request, [
            'title' => 'required',
            'description' => 'required',
        ]);


        $edit = Book::find($id)->update($request->all());


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


    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        Book::find($id)->delete();
        return response()->json(['done']);
    }
}

Step 4: Create Blade File


In this step, we have to create only one blade file that will manage create, update and delete operation of books module with vue js.

In this file, I added jquery, bootstrap js, and css, vue.js, Vue-resource.min.js, toaster js and css for notification in this blade file.

So, let's create manage-vue.blade.php file on following way:

resources/views/manage-vue.blade.php

<!DOCTYPE html>
<html>
<head>
<title>Laravel Vue JS Book CRUD</title>
<meta id="token" name="token" value="{{ csrf_token() }}">
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha/css/bootstrap.css">
</head>
<body>


<div class="container" id="manage-vue">


<div class="row">
    <div class="col-lg-12 margin-tb">
        <div class="pull-left">
            <h2>Laravel Vue JS Book CRUD</h2>
        </div>
        <div class="pull-right">
<button type="button" class="btn btn-success" data-toggle="modal" data-target="#create-book">
  Create Book
</button>
        </div>
    </div>
</div>


<!-- Book Listing -->
<table class="table table-bordered">
<tr>
<th>Title</th>
<th>Description</th>
        <th>Author</th>
<th width="200px">Action</th>
</tr>
<tr v-for="book in books">
<td>@{{ book.title }}</td>
<td>@{{ book.description }}</td>
        <td>@{{ book.author }}</td>
<td>
      <button class="btn btn-primary" @click.prevent="editBook(book)">Edit</button>
      <button class="btn btn-danger" @click.prevent="deleteBook(book)">Delete</button>
</td>
</tr>
</table>


<!-- Pagination -->
<nav>
        <ul class="pagination">
            <li v-if="pagination.current_page > 1">
                <a href="#" aria-label="Previous"
                   @click.prevent="changePage(pagination.current_page - 1)">
                    <span aria-hidden="true">«</span>
                </a>
            </li>
            <li v-for="page in pagesNumber"
                v-bind:class="[ page == isActived ? 'active' : '']">
                <a href="#"
                   @click.prevent="changePage(page)">@{{ page }}</a>
            </li>
            <li v-if="pagination.current_page < pagination.last_page">
                <a href="#" aria-label="Next"
                   @click.prevent="changePage(pagination.current_page + 1)">
                    <span aria-hidden="true">»</span>
                </a>
            </li>
        </ul>
    </nav>


    <!-- Create Book Modal -->
<div class="modal fade" id="create-book" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
        <h4 class="modal-title" id="myModalLabel">Create Book</h4>
      </div>
      <div class="modal-body">


      <form method="POST" enctype="multipart/form-data" v-on:submit.prevent="createBook">


      <div class="form-group">
<label for="title">Title:</label>
<input type="text" name="title" class="form-control" v-model="newBook.title" />
<span v-if="formErrors['title']" class="error text-danger">@{{ formErrors['title'] }}</span>
</div>


<div class="form-group">
<label for="title">Description:</label>
<textarea name="description" class="form-control" v-model="newBook.description"></textarea>
<span v-if="formErrors['description']" class="error text-danger">@{{ formErrors['description'] }}</span>
</div>

          <div class="form-group">
            <label for="author">Author:</label>
            <input type="text" name="author" class="form-control" v-model="newBook.author" />
            <span v-if="formErrors['author']" class="error text-danger">@{{ formErrors['author'] }}</span>
          </div>


<div class="form-group">
<button type="submit" class="btn btn-success">Submit</button>
</div>


      </form>

     
      </div>
    </div>
  </div>
</div>


<!-- Edit Book Modal -->
<div class="modal fade" id="edit-book" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
        <h4 class="modal-title" id="myModalLabel">Edit Book</h4>
      </div>
      <div class="modal-body">


      <form method="POST" enctype="multipart/form-data" v-on:submit.prevent="updateBook(fillBook.id)">


      <div class="form-group">
<label for="title">Title:</label>
<input type="text" name="title" class="form-control" v-model="fillBook.title" />
<span v-if="formErrorsUpdate['title']" class="error text-danger">@{{ formErrorsUpdate['title'] }}</span>
</div>


<div class="form-group">
<label for="title">Description:</label>
<textarea name="description" class="form-control" v-model="fillBook.description"></textarea>
<span v-if="formErrorsUpdate['description']" class="error text-danger">@{{ formErrorsUpdate['description'] }}</span>
</div>

          <div class="form-group">
            <label for="author">Author:</label>
            <input type="text" name="author" class="form-control" v-model="fillBook.author" />
            <span v-if="formErrorsUpdate['author']" class="error text-danger">@{{ formErrorsUpdate['author'] }}</span>
          </div>


<div class="form-group">
<button type="submit" class="btn btn-success">Submit</button>
</div>


      </form>


      </div>
    </div>
  </div>
</div>


</div>


<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha/js/bootstrap.min.js"></script>


<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/js/toastr.min.js"></script>
        <link href="//cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/css/toastr.min.css" rel="stylesheet">


<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.26/vue.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/vue.resource/0.9.3/vue-resource.min.js"></script>


<script type="text/javascript" src="/js/book.js"></script>


</body>
</html>

Step 5: Create JS File


In last step we require to create one book.js file, first we have to create new folder "js" in public directory and then create book.js file inside of this folder.

book.js file through we can manage book pagination, create edit delete task and also ajax method.

public/js/book.js

Vue.http.headers.common['X-CSRF-TOKEN'] = $("#token").attr("value");


new Vue({


  el: '#manage-vue',


  data: {
    books: [],
    pagination: {
        total: 0,
        per_page: 2,
        from: 1,
        to: 0,
        current_page: 1
      },
    offset: 4,
    formErrors:{},
    formErrorsUpdate:{},
    newBook : {'title':'','description':'','author':''},
    fillBook : {'title':'','description':'','author':'','id':''}
  },


  computed: {
        isActived: function () {
            return this.pagination.current_page;
        },
        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 = [];
            while (from <= to) {
                pagesArray.push(from);
                from++;
            }
            return pagesArray;
        }
    },


  ready : function(){
  this.getVueBooks(this.pagination.current_page);
  },


  methods : {


        getVueBooks: function(page){
          this.$http.get('/vuebooks?page='+page).then((response) => {
            this.$set('books', response.data.data.data);
            this.$set('pagination', response.data.pagination);
          });
        },


        createBook: function(){
  var input = this.newBook;
  this.$http.post('/vuebooks',input).then((response) => {
    this.changePage(this.pagination.current_page);
this.newBook = {'title':'','description':'','author':''};
$("#create-book").modal('hide');
toastr.success('Book Created Successfully.', 'Success Alert', {timeOut: 5000});
  }, (response) => {
this.formErrors = response.data;
    });
},


      deleteBook: function(book){
        this.$http.delete('/vuebooks/'+book.id).then((response) => {
            this.changePage(this.pagination.current_page);
            toastr.success('Book Deleted Successfully.', 'Success Alert', {timeOut: 5000});
        });
      },


      editBook: function(book){
          this.fillBook.title = book.title;
          this.fillBook.id = book.id;
          this.fillBook.description = book.description;
          this.fillBook.author = book.author;
          $("#edit-book").modal('show');
      },


      updateBook: function(id){
        var input = this.fillBook;
        this.$http.put('/vuebooks/'+id,input).then((response) => {
            this.changePage(this.pagination.current_page);
            this.fillBook = {'title':'','description':'','author':'','id':''};
            $("#edit-book").modal('hide');
            toastr.success('Book Updated Successfully.', 'Success Alert', {timeOut: 5000});
          }, (response) => {
              this.formErrorsUpdate = response.data;
          });
      },


      changePage: function (page) {
          this.pagination.current_page = page;
          this.getVueBooks(page);
      }


  }


});

Comments

Popular posts from this blog

Laravel 5 Chart example using Charts Package

Laravel Stats Tracker

PHPMyBackup - A PHP MySQL differential backup script