Technology

jQuery AJAX within Laravel Blade Templates

October 26th, 2015 Posted by Uncategorized 0 comments on “jQuery AJAX within Laravel Blade Templates”

Here’s how to create an AJAX call in Laravel.

Note that none of the login and authentication routes or pages are included in this guide. To set those up refer to the official Laravel page on authentication. Also note that for the code examples only the relevant code is shown, there may be code in these files that isn’t shown.

 

Set up the routes

This example uses two routes, one to serve the page and another to interface with the AJAX calls. These routes are intentionally hidden behind the ‘auth’ middleware, the AJAX call used later will handle that.

// app\Http\routes.php

Route::group(['middleware' => 'auth'], function()
{
  Route::get('my-data', 'DataController@getData');
  Route::post('edit-data', 'DataController@editData');
});

 

Configure the middleware

In Laravel 5.0 you can configure the VerifyCsrfToken middleware to skip checking AJAX calls.

// app\Http\Middleware\VerifyCsrfToken.php

public function handle($request, Closure $next)
{
  // Checks if request is an ajax call
  if ($request->ajax())
  {
    return $next($request);
  }
  return parent::handle($request, $next);
}

In Laravel 5.1 there is a variable provided for URIs that should be ignored by CSRF middleware.

// app\Http\Middleware\VerifyCsrfToken.php

class VerifyCsrfToken extends BaseVerifier
{
  protected $except = [
    'edit-data',
  ];
}

 

Set up the controller

There are two very simple controller endpoints for this app. Function getData simply uses the Auth facade to return a page with the user information. Function editData takes a Request instance, does some validation, then saves the information and returns a json response.

// app\Http\Controllers\DataController.php

class DataController extends Controller {

  /**
   * Display a page containing some user data
   *
   * @return View
   */
  public function getData()
  {
    $user = Auth::user();
    return view('users.myData', $user->toArray());
  }
 
  /**
   * Edit user data
   *  This will be called by the jQuery to store the data using AJAX
   * 
   * @param  \Illuminate\Http\Request  $request
   * @return \Illuminate\Http\Response
   */
  public function editData(Request $request)
  {
    // Validate the input
    $this->validate($request, [
      'name' => 'min:2|max:255',
      'email' => 'email|max:255',
    ]);
 
    // Set the user instance to the current user
    $user = Auth::user();
 
    // Update the name if it is in the request
    if ($request->includes('name'))
    {
      $user->name = $request->input('name');
    }
 
    // Update the email if it is in the request
    if ($request->has('email'))
    {
      $user->email = $request->input('email');
    }
 
    $user->save();
 
    return response()->json(['succes', 'Information updated']);
  }
}

 

Create the view

An example view for displaying the data. This example doesn’t use a form, but a series of individual inputs. As a result, jQuery has a greater level of flexibility when saving the data. For example, if there was a table with a list of several users (say for an admin console), then the jQuery could walk over all the inputs and send post requests for each user with the click of one save button. A form would send a mixed bag of user data that would require creating a special api endpoint on the backend to handle. The other choice would be to create a separate form for each user, but that would mean a save button for each user as well, which could be annoying to use.

<!-- resources/views/users/myData.blade.php -->
<!DOCTYPE html>
  <html>
    <head>
      <title>User Information</title>
    </head>
  <body>
    <button id="save-data" class="btn btn-primary" type="button">Save Information</button>
    <div>
      Name:
      <input class="name-input" type="text" value="{{ $name }}" data-userid="{{ $id }}" />
    </div>
    <div>
      Email:
     <input class="email-input" type="email" value="{{ $email }}" data-userid="{{ $id }}" />
    </div>
  </body>
  <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
  <script src="js/all.js"></script>
</html>

 

Write the javascript

This javascript uses jQuery to walk over all the inputs on the page, checks if the value has been changed, then sends a request to the server with the new data. It could be optimized by putting the name and email in one single request, especially since the backend has already been configured to handle this, but this example leaves out the extra logic necessary for the sake of simplicity.

Also note that the cookie with the laravel_session variable is already included in the post request sent to the server, so the user is already considered logged in, and the request can be sent to routes behind auth middleware without any extra configuration.

// public\js\all.js

$("#save-data").click(function() {
  // Save all of the names (only one in this example, but can be expanded)
  $('.name-input').each(function() {
    // Create an object with the new value and pass it to the save function
    saveInput($(this), { name: $(this).val() });
  });
  // Save all of the emails (only one in this example, but can be expanded)
  $('.email-input').each(function() {
    // Create an object with the new value and pass it to the save function
    saveInput($(this), { email: $(this).val() });
  });
});
 
// Save all the changed inputs using ajax
function saveInput(element, postData) {
  // Check if the value has changed
  if (element.val() !== element.attr('value')) {
    // Upload the new value to the server
    $.post('/edit-data', postData)
      .fail(function(data) {  // Ignore successful uploads, but display errors
        alert("There was an error with saving data: " + element.val() );
      });
  }
}

[/vc_column_text][/vc_column][/vc_row]

Call us now to talk over your project and

get an expert’s opinion