codovel

We no longer support this blog. Please visit this site instead. www.codovel.com

Sunday, June 19, 2016

Complete laravel ajax CRUD, search, sort and pagination

Suppose that your project root folder is here C:\wamp\www\test_laravel.

Please download this file public.rar and extract to your public folder (C:\wamp\www\test_laravel\public)

Step 1: Create table products in MySQL database


or you can download sample data from here.

Step 2: Connect your Laravel project to MySQL database.Go to edit this file C:\wamp\www\test_laravel\.env and update your database information


Step 3: Create model file Product.php in C:\wamp\www\test_laravel\app

Product.php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Product extends Model
{

}

Step 4: Edit route file (C:\wamp\www\test_laravel\app\Http\routes.php) and add
Route::controller('product', 'ProductController');

Step 5: Create some view files index.blade.php, list.blade.php, create.blade.php, update.blade.php, _form.blade.php in C:\wamp\www\test_laravel\resources\views\product (please create product folder if not exist)

index.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>Laravel Tutorials</title>
    <!-- Styles -->
    <link href="{{ asset('bootstrap-3.3.6/css/bootstrap.min.css') }}" rel="stylesheet">
</head>
<body>
<style>
    .loading {
        background: lightgoldenrodyellow url('{{asset('images/processing.gif')}}') no-repeat center 65%;
        height: 80px;
        width: 100px;
        position: fixed;
        border-radius: 4px;
        left: 50%;
        top: 50%;
        margin: -40px 0 0 -50px;
        z-index: 2000;
        display: none;
    }
</style>
<div class="container-fluid">
    <div class="row"></div>
    <div class="row">
        <div class="col-md-3"></div>
        <div class="col-md-6">
            <div id="content"></div>
        </div>
        <div class="col-md-3"></div>
    </div>
    <div class="loading"></div>
</div>
<!-- JavaScripts -->
<script src="{{ asset('js/jquery-1.11.2.min.js') }}"></script>
<script src="{{ asset('bootstrap-3.3.6/js/bootstrap.min.js') }}"></script>
<script>
    function ajaxLoad(filename, content) {
        content = typeof content !== 'undefined' ? content : 'content';
        $('.loading').show();
        $.ajax({
            type: "GET",
            url: filename,
            contentType: false,
            success: function (data) {
                $("#" + content).html(data);
                $('.loading').hide();
            },
            error: function (xhr, status, error) {
                alert(xhr.responseText);
            }
        });
    }
    $(document).ready(function () {
        ajaxLoad('product/list');
    });
</script>
</body>
</html>

list.blade.php
<h1 class="page-header">Product List
    <div class="pull-right">
        <a href="javascript:ajaxLoad('product/create')" class="btn btn-primary pull-right"><i
                    class="glyphicon glyphicon-plus-sign"></i> New</a>
    </div>
</h1>
<div class="col-sm-7 form-group">
    <div class="input-group">
        <input class="form-control" id="search" value="{{ Session::get('product_search') }}"
               onkeydown="if (event.keyCode == 13) ajaxLoad('{{url('product/list')}}?ok=1&search='+this.value)"
               placeholder="Search..."
               type="text">

        <div class="input-group-btn">
            <button type="button" class="btn btn-default"
                    onclick="ajaxLoad('{{url('product/list')}}?ok=1&search='+$('#search').val())"><i
                        class="glyphicon glyphicon-search"></i>
            </button>
        </div>
    </div>
</div>
<table class="table table-bordered table-striped">
    <thead>
    <tr>
        <th width="50px" style="text-align: center">No</th>
        <th>
            <a href="javascript:ajaxLoad('product/list?field=name&sort={{Session::get("product_sort")=="asc"?"desc":"asc"}}')">
                Name
            </a>
            <i style="font-size: 12px"
               class="glyphicon  {{ Session::get('product_field')=='name'?(Session::get('product_sort')=='asc'?'glyphicon-sort-by-alphabet':'glyphicon-sort-by-alphabet-alt'):'' }}">
            </i>
        </th>
        <th>
            <a href="javascript:ajaxLoad('product/list?field=unitprice&sort={{Session::get("product_sort")=="asc"?"desc":"asc"}}')">
                Unitprice
            </a>
            <i style="font-size: 12px"
               class="glyphicon  {{ Session::get('product_field')=='unitprice'?(Session::get('product_sort')=='asc'?'glyphicon-sort-by-alphabet':'glyphicon-sort-by-alphabet-alt'):'' }}">
            </i>
        </th>
        <th width="140px"></th>
    </tr>
    </thead>
    <tbody>
    <?php $i = 1;?>
    @foreach($products as $key=>$product)
        <tr>
            <td align="center">{{$i++}}</td>
            <td>{{$product->name}}</td>
            <td align="right">$ {{$product->unitprice}}</td>
            <td style="text-align: center">
                <a class="btn btn-primary btn-xs" title="Edit"
                   href="javascript:ajaxLoad('product/update/{{$product->id}}')">
                    <i class="glyphicon glyphicon-edit"></i> Edit</a>
                <a class="btn btn-danger btn-xs" title="Delete"
                   href="javascript:if(confirm('Are you sure want to delete?')) ajaxLoad('product/delete/{{$product->id}}')">
                    <i class="glyphicon glyphicon-trash"></i> Delete
                </a>
            </td>
        </tr>
    @endforeach
    </tbody>
</table>
<div class="pull-right">{!! str_replace('/?','?',$products->render()) !!}</div>
<div class="row">
    <i class="col-sm-12">
        Total: {{$products->total()}} records
    </i>
</div>
<script>
    $('.pagination a').on('click', function (event) {
        event.preventDefault();
        ajaxLoad($(this).attr('href'));
    });
</script>

create.blade.php
<h2 class="page-header">New Product</h2>
{!! Form::open(["id"=>"frm","class"=>"form-horizontal"]) !!}
@include("product._form")
{!! Form::close() !!}


update.blade.php
<h2 class="page-header">Edit Product</h2>
{!! Form::model($product,["id"=>"frm","class"=>"form-horizontal"]) !!}
@include("product._form")
{!! Form::close() !!}


_form.blade.php
<div class="form-group required" id="form-name-error">
    {!! Form::label("name","Name",["class"=>"control-label col-md-3"]) !!}
    <div class="col-md-6">
        {!! Form::text("name",null,["class"=>"form-control required","id"=>"focus"]) !!}
        <span id="name-error" class="help-block"></span>
    </div>
</div>
<div class="form-group required" id="form-unitprice-error">
    {!! Form::label("unitprice","Unitprice",["class"=>"control-label col-md-3"]) !!}
    <div class="col-md-6">
        {!! Form::text("unitprice",null,["class"=>"form-control required"]) !!}
        <span id="unitprice-error" class="help-block"></span>
    </div>
</div>
<div class="form-group">
    <div class="col-md-6 col-md-push-3">
        <a href="javascript:ajaxLoad('product/list')" class="btn btn-danger"><i
                    class="glyphicon glyphicon-backward"></i>
            Back</a>
        {!! Form::button("<i class='glyphicon glyphicon-floppy-disk'></i> Save",["type" => "submit","class"=>"btn
    btn-primary"])!!}
    </div>
</div>
<script>
    $("#frm").submit(function (event) {
        event.preventDefault();
        $('.loading').show();
        var form = $(this);
        var data = new FormData($(this)[0]);
        var url = form.attr("action");
        $.ajax({
            type: "POST",
            url: url,
            data: data,
            async: false,
            cache: false,
            contentType: false,
            processData: false,
            success: function (data) {
                if (data.fail) {
                    $('#frm input.required, #frm textarea.required').each(function () {
                        index = $(this).attr('name');
                        if (index in data.errors) {
                            $("#form-" + index + "-error").addClass("has-error");
                            $("#" + index + "-error").html(data.errors[index]);
                        }
                        else {
                            $("#form-" + index + "-error").removeClass("has-error");
                            $("#" + index + "-error").empty();
                        }
                    });
                    $('#focus').focus().select();
                } else {
                    $(".has-error").removeClass("has-error");
                    $(".help-block").empty();
                    $('.loading').hide();
                    ajaxLoad(data.url, data.content);
                }
            },
            error: function (xhr, textStatus, errorThrown) {
                alert(errorThrown);
            }
        });
        return false;
    });
</script>

Step 6: Create controller file ProductController.php in here C:\wamp\www\test_laravel\app\Http\Controllers 
<?php
namespace App\Http\Controllers;

use App\Product;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Input;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Validator;

class ProductController extends Controller
{
    public function getIndex()
    {
        return view('product.index');
    }

    public function getList()
    {
        Session::put('product_search', Input::has('ok') ? Input::get('search') : (Session::has('product_search') ? Session::get('product_search') : ''));
        Session::put('product_field', Input::has('field') ? Input::get('field') : (Session::has('product_field') ? Session::get('product_field') : 'name'));
        Session::put('product_sort', Input::has('sort') ? Input::get('sort') : (Session::has('product_sort') ? Session::get('product_sort') : 'asc'));
        $products = Product::where('name', 'like', '%' . Session::get('product_search') . '%')
            ->orderBy(Session::get('product_field'), Session::get('product_sort'))->paginate(8);
        return view('product.list', ['products' => $products]);
    }

    public function getUpdate($id)
    {
        return view('product.update', ['product' => Product::find($id)]);
    }

    public function postUpdate($id)
    {
        $product = Product::find($id);
        $rules = ["unitprice" => "required|numeric"];
        if ($product->name != Input::get('name'))
            $rules += ['name' => 'required|unique:products'];
        $validator = Validator::make(Input::all(), $rules);
        if ($validator->fails()) {
            return array(
                'fail' => true,
                'errors' => $validator->getMessageBag()->toArray()
            );
        }
        $product->name = Input::get('name');
        $product->unitprice = Input::get('unitprice');
        $product->save();
        return ['url' => 'product/list'];
    }

    public function getCreate()
    {
        return view('product.create');
    }

    public function postCreate()
    {
        $validator = Validator::make(Input::all(), [
            "name" => "required|unique:products",
            "unitprice" => "required|numeric"
        ]);
        if ($validator->fails()) {
            return array(
                'fail' => true,
                'errors' => $validator->getMessageBag()->toArray()
            );
        }
        $product = new Product();
        $product->name = Input::get('name');
        $product->unitprice = Input::get('unitprice');
        $product->save();
        return ['url' => 'product/list'];
    }

    public function getDelete($id)
    {
        Product::destroy($id);
        return Redirect('product/list');
    }

}

How to test? open your browser and type http://localhost/test_laravel/public/product. You will see this screen


20 comments:

About said...

Nice!

Evaria Ayu Nurjana said...
This comment has been removed by the author.
Evaria Ayu Nurjana said...

if ($validator->fails()) {
return array(
'fail' => true,
'errors' => $validator->getMessageBag()->toArray()
);
}

How do I catch the error and passing to alert?
It just passing to the web just like this, and alert didn't show this
{"fail":true,"errors":{"user_id":["The user id field is required."]}}

Senghok Eang said...

Hi Evaria,

It is ajax based CRUD, so you can check in javascript like this
$.ajax({
....
...
success: function (data) {
if (data.fail) {
alert(data.errors['user_id']);
},
....
...
});

Evaria Ayu Nurjana said...

Where should I add the code at list.blade.php or index.blade.php? I'm sorry, I am still learning ajax and still newbie

Evaria Ayu Nurjana said...

I've tried add the code
success: function (data) {
if (data.fail) {
$('#frm input.required, #frm select.required').each(function () {
index = $(this).attr('name');
$('.loading').hide();
if (index in data.errors) {
$("#form-" + index + "-error").addClass("has-error");
$("#" + index + "-error").html(data.errors[index]);
}
else {
$("#form-" + index + "-error").removeClass("has-error");
$("#" + index + "-error").empty();
}
});
$('#focus').focus().select();
alert(data.errors['user_id']);
...
still didn't work

Senghok Eang said...

It is validation in form so you should put this code in _form.php

Sergej Leginkov said...

Hi Senghok,

thanks for your tutorial Could you please also provide the retoute structure for Laravel 5.3 ?

As route:controller isn't working here anymore:
Route::controller('product', 'ProductController');

Help is much appreciated.

Dusty Darrell said...

This is an example of AJAX but a BAD example of a controller.

Rifki Chaplin said...

this is my routing, but when i save or update data, i got error "method not Allow".
can u help me ??

| GET|HEAD | product | | App\Http\Controllers\ProductsController@index | web |
| | GET|HEAD | product/create | | App\Http\Controllers\ProductsController@getCreate | web |
| | GET|HEAD | product/delete/{id} | | App\Http\Controllers\ProductsController@getDelete | web |
| | GET|HEAD | product/list | | App\Http\Controllers\ProductsController@getList | web |
| | POST | product/postcreate | | App\Http\Controllers\ProductsController@postCreate | web |
| | GET|HEAD | product/update/{id} | | App\Http\Controllers\ProductsController@getUpdate | web

Erick Nobleza said...

I'm getting this error "NotFoundHttpException in RouteCollection.php line 161:"

Fasiray said...

Thanks

Route::group(['middleware' => 'web'], function(){
Route::get('product','ProductController@getIndex');
Route::get('product/update/{id}','ProductController@getUpdate');
Route::post('product/update/','ProductController@postUpdate');
Route::get('product/create','ProductController@getCreate');
Route::post('product/create/','ProductController@postCreate');
Route::get('product/list','ProductController@getList');
Route::post('product/delete/{id}','ProductController@getDelete');
});

info care said...

I'm getting this error NotFoundHttpException in RouteCollection.php line 161:pls solve

Gautam said...

hi,

Is there any way i can contact you directly. This regarding article writing. Please let me know by replying to may email.

Nitesh Kumar said...

I really appreciate information shared above. It’s of great help. If someone want to learn Online (Virtual) instructor lead live training in AJAX, kindly contact us http://www.maxmunus.com/contact
MaxMunus Offer World Class Virtual Instructor led training on AJAX. We have industry expert trainer. We provide Training Material and Software Support. MaxMunus has successfully conducted 100000+ trainings in India, USA, UK, Australlia, Switzerland, Qatar, Saudi Arabia, Bangladesh, Bahrain and UAE etc.
For Demo Contact us.
Nitesh Kumar
MaxMunus
E-mail: nitesh@maxmunus.com
Skype id: nitesh_maxmunus
Ph:(+91) 8553912023
http://www.maxmunus.com/




Fabio Alexandre Pszepiura said...

Hello, First I want to thank for the example that is being very useful for some studies that I am doing.
I can't download the project files, so I find difficults in code $products->render() and $products->total(). Can you help me?

Anonymous said...

hello i thank you for this post. i used a part of it by modifying it but it works for me with laravel 5.3. i used only the search part.

Laravel Scots said...

Nice Article, keep Writing, Do you know you can also post your laravel related articles
on http://www.laravelinterviewquestions.com/submit-an-article too

Eric Kwakye said...

the download link is not working please help. or email tipsysmino@gmail.com

webwing said...

Nice post! thank you.
affordable web development company | best web design services