Thứ Tư, 2 tháng 11, 2016

Laravel 5 and Vue.Js : Simple C.R.U.D with Notification and Pagination Example in Laravel 5.3


Laravel Vue.Js Tutorial - How to create simple CRUD (Create, Read, Update, Delete) operations using Laravel 5.3 and vue.js with beauty Notification and pagination in laravel 5.3? at the previews lessons, we have create simple Ajax CRUD in Laravel 5.3, please read Laravel 5 CRUD using AJAX & Modals + Bootstrap Template.

CRUD with Vue.Js in Laravel 5.3

Step 1 - you must create new database "laravelvuejscrud", i'm using MySQL database.
Next, we will create new project using Laravel 5.3

Simple C.R.U.D with Notification and Pagination Example in Laravel 5.3

Create Laravel 5.3 CRUD Project

Install Laravel 5.3 using Composer

cd c:\server\htdocs\
...
composer create-project --prefer-dist laravel/laravel laravelvuejscrud
...
cd laravelvuejscrud

Create Connection to your Database (MySQL Database)

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravelvuejs
DB_USERNAME=root
DB_PASSWORD=yourpassword

Create Table and Migration

php artisan make:migration create_table_blog_tabel

In your new migration file will stored on database\migrations\2016_11_02_210301_create_blog_table.php

public function up() {
      Schema::create('blog_post', function (Blueprint $table) {
        $table->increments('id');
        $table->string('title');
        $table->string('description');
        $table->timestamps();
      });
    }
    public function down() {
        Schema::drop('blog_post');
    }

Next, run Migration

php artisan migrate

Create Model (Blog.php)

php artisan make:model Blog

Your new model will stored on app\Blog.php

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Blog extends Model
{
  protected $table ='blog_post';
  public $fillable = ['title','description'];
}

Create Controller (BlogController.php)

php artisan make:controller BlogController --resource

Your controller will stored on app\Http\Controllers\BlogController.php

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Blog;
use App\Http\Requests;
use Validator;
use Response;
use Illuminate\Support\Facades\Input;

class BlogController extends Controller
{
    public function vueCrud(){
      return view('/vuejscrud/index');
    }

    public function index()
    {
        $items = Blog::latest()->paginate(6);
        $response = [
          'pagination' => [
            'total' => $items->total(),
            'per_page' => $items->perPage(),
            'current_page' => $items->currentPage(),
            'last_page' => $items->lastPage(),
            'from' => $items->firstItem(),
            'to' => $items->lastItem()
          ],
          'data' => $items
        ];
        return response()->json($response);
    }

    public function store(Request $request)
    {
        $this->validate($request,[
          'title' => 'required',
          'description' => 'required',
        ]);
        $create = Blog::create($request->all());
        return response()->json($create);
    }

    public function update(Request $request, $id)
    {
      $this->validate($request,[
        'title' => 'required',
        'description' => 'required',
      ]);
      $edit = Blog::find($id)->update($request->all());
      return response()->json($edit);
    }
    
    public function destroy($id)
    {
        Blog::find($id)->delete();
        return response()->json(['done']);
    }
}

Create Routes

Route::group(['middleware' => ['web']], function() {
  Route::get('/vuejscrud', 'BlogController@vueCrud');
  Route::resource('vueitems','BlogController');
});

Next, we wil working with views,

Views

Create new file for our Master Blade templates, named with "app.blade.php" that stored on resources\views\app.blade.php

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Simple Laravel Vue.Js CRUD</title>
    <meta id="token" name="token" value="{{ csrf_token() }}">
    <!-- Bootstrap -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css">
    <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
      <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.2/html5shiv.js"></script>
      <script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->
  </head>
  <body>
    <div class="container" id="manage-vue">
      @yield('content')
    </div>
    <!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
    <!-- Include all compiled plugins (below), or include individual files as needed -->
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/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://cdnjs.cloudflare.com/ajax/libs/vue-resource/1.0.3/vue-resource.min.js"></script>
    <script type="text/javascript" src="/js/blog.js"></script>
  </body>
</html>

Create New Page (index.blade.php)

This page will stored on resources\views\vuejscrud\index.blade.php

@extends('app')
@section('content')
  <div class="form-group row add">
    <div class="col-md-12">
      <h1>Simple Laravel Vue.Js Crud</h1>
    </div>
    <div class="col-md-12">
      <button type="button" data-toggle="modal" data-target="#create-item" class="btn btn-primary">
        Create New Post
      </button>
    </div>
  </div>
  <div class="row">
    <div class="table-responsive">
      <table class="table table-borderless">
        <tr>
          <th>Title</th>
          <th>Description</th>
          <th>Actions</th>
        </tr>
        <tr v-for="item in items">
          <td>@{{ item.title }}</td>
          <td>@{{ item.description }}</td>
          <td>
            <button class="edit-modal btn btn-warning" @click.prevent="editItem(item)">
              <span class="glyphicon glyphicon-edit"></span> Edit
            </button>
            <button class="edit-modal btn btn-danger" @click.prevent="deleteItem(item)">
              <span class="glyphicon glyphicon-trash"></span> Delete
            </button>
          </td>
        </tr>
      </table>
    </div>
  </div>
  <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 Item Modal -->
  <div class="modal fade" id="create-item" 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 New Post</h4>
        </div>
        <div class="modal-body">
          <form method="post" enctype="multipart/form-data" v-on:submit.prevent="createItem">
            <div class="form-group">
              <label for="title">Title:</label>
              <input type="text" name="title" class="form-control" v-model="newItem.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="newItem.description">
              </textarea>
              <span v-if="formErrors['description']" class="error text-danger">
                @{{ formErrors['description'] }}
              </span>
            </div>
            <div class="form-group">
              <button type="submit" class="btn btn-success">Submit</button>
            </div>
          </form>
        </div>
      </div>
    </div>
  </div>
<!-- Edit Item Modal -->
<div class="modal fade" id="edit-item" 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 Blog Post</h4>
      </div>
      <div class="modal-body">
        <form method="post" enctype="multipart/form-data" v-on:submit.prevent="updateItem(fillItem.id)">
          <div class="form-group">
            <label for="title">Title:</label>
            <input type="text" name="title" class="form-control" v-model="fillItem.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="fillItem.description">
            </textarea>
            <span v-if="formErrorsUpdate['description']" class="error text-danger">
              @{{ formErrorsUpdate['description'] }}
            </span>
          </div>
          <div class="form-group">
            <button type="submit" class="btn btn-success">Submit</button>
          </div>
        </form>
      </div>
    </div>
  </div>
</div>
@stop

Finnally, this step we will working with JavaScript,

blog.js (public\js\blog.js)

Create new file in public\js\blog.js

Vue.http.headers.common['X-CSRF-TOKEN'] = $("#token").attr("value");
new Vue({
  el :'#manage-vue',
  data :{
    items: [],
    pagination: {
      total: 0,
      per_page: 2,
      from: 1,
      to: 0,
      current_page: 1
    },
    offset: 4,
    formErrors:{},
    formErrorsUpdate:{},
    newItem : {'title':'','description':''},
    fillItem : {'title':'','description':'','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.getVueItems(this.pagination.current_page);
  },
  methods: {
    getVueItems: function(page) {
      this.$http.get('/vueitems?page='+page).then((response) => {
        this.$set('items', response.data.data.data);
        this.$set('pagination', response.data.pagination);
      });
    },
    createItem: function() {
      var input = this.newItem;
      this.$http.post('/vueitems',input).then((response) => {
        this.changePage(this.pagination.current_page);
        this.newItem = {'title':'','description':''};
        $("#create-item").modal('hide');
        toastr.success('Post Created Successfully.', 'Success Alert', {timeOut: 5000});
      }, (response) => {
        this.formErrors = response.data;
      });
    },
    deleteItem: function(item) {
      this.$http.delete('/vueitems/'+item.id).then((response) => {
        this.changePage(this.pagination.current_page);
        toastr.success('Post Deleted Successfully.', 'Success Alert', {timeOut: 5000});
      });
    },
    editItem: function(item) {
      this.fillItem.title = item.title;
      this.fillItem.id = item.id;
      this.fillItem.description = item.description;
      $("#edit-item").modal('show');
    },
    updateItem: function(id) {
      var input = this.fillItem;
      this.$http.put('/vueitems/'+id,input).then((response) => {
        this.changePage(this.pagination.current_page);
        this.newItem = {'title':'','description':'','id':''};
        $("#edit-item").modal('hide');
        toastr.success('Item Updated Successfully.', 'Success Alert', {timeOut: 5000});
      }, (response) => {
        this.formErrors = response.data;
      });
    },
    changePage: function(page) {
      this.pagination.current_page = page;
      this.getVueItems(page);
    }
  }
});

Video tutorial C.R.U.D with Notification and Pagination Example using Vue.Js



Laravel 5.3 Simple Ajax CRUD



Subscribe for more tutorials.
Download Full source code C.R.U.D with Notification and Pagination Example in Laravel 5.3 and Vue.js https://goo.gl/wp9xwf

See you next lessons ...

Không có nhận xét nào:

Đăng nhận xét