In this tutorial I want to show you how to build a web application using the Laravel framework and JavaScript Ajax. For example, you could deploy the app as a mobile app using the Android web view widget.


Step 1: Requirements (installing Composer and Laravel)

To install external dependencies, we need the php package manager Composer. Download it here and install it on your local machine. I recommend installing composer globally and for all system users.

Since Laravel is nothing more than a package, we will use Composer to download and install it.

composer global require laravel/installer

After the installation, create a new Laravel project with the following command. (Replace „web-app“ with the project name of your choice. Laravel creates a directory according to the project name).

laravel new web-app

Now you can run the application by running the following command:

php artisan serve


Step 2: Creating controller, model, migration and a seed

Let’s create some files and classes to build our project.


Create a model called Grocery.

php artisan make:model Grocery


Create a controller called GroceryController.

php artisan make:controller GroceryController


Create a database migration called create_groceries_tables. It provides all required information to insert the table create_groceries_tables into the database.

php artisan make:migration create_groceries_table

Add the following code to the migration located in the directory database/migrations:

public function up()
   Schema::create('groceries', function (Blueprint $table) {


Create a seed called GroceriesSeed.

php artisan make:seed GroceriesSeeder

Add the following code to the seeder located in the directory database/seeds:

public function run()
    'title' => 'Apple',
    'category' => 'fruits',
    'created_at' => date("Y-m-d H:i:s"),
    'updated_at' => date("Y-m-d H:i:s")
    'title' => 'Banana',
    'category' => 'fruits',
    'created_at' => date("Y-m-d H:i:s"),
    'updated_at' => date("Y-m-d H:i:s")
    'title' => 'Orange',
    'category' => 'fruits',
    'created_at' => date("Y-m-d H:i:s"),
    'updated_at' => date("Y-m-d H:i:s")

The central file that controls the seeds is the file called DatabaseSeeder.php located in the seeds directory. You need to add the following line to it for the seeder to work:



Step 3: Setup the database

Create a database (on your machine using a local database server) and add the sign-in information to the .env file.


Let’s migrate the table to our database using the migration file. At the same time, the test data from the seed should be inserted. Use the following command to do both with just one command:

php artisan migrate --seed


Step 4: Add code to GroceryController

We need a method inside the GroceryController which retrieves grocery data from our database. To get this done, we use the Laravel ORM called eloquent. Eloquent makes it easier to retrieve data from our database. It’s based on data models, which we created at step 2 (the model Grocery). Add the class reference above the GroceryController class:

use App\Grocery;

After this, add the index method inside the GroceryController class. It returns a list of existing groceries in json format.

public function index() {
// Load all columns in descending order based on the 'id' column.
$groceries = Grocery::orderBy('id', 'desc')->get();

// Return data as JSON
return response()->json($groceries);


Step 5: Add required routes

Currently the controller can’t be accessed because a suitable route doesn’t exist. Let’s add it to the web.php file located in the routes directory.

Route::get('groceries', function() { 
  return view('grocery-list'); 
Route::get('groceries/get', 'GroceryController@index');

The first route is just the one we use to access the grocery list which we’ll create in the next step. To test the second route, try to access the url http://localhost:8000/groceries/get. If the route works, you should see a JSON response like this:


Laravel Ajax JSON Result


Step 6: Create view, add layout

Now we want to create a view with some bootstrap layout to show the data provided by the controller. Create the file grocery-list.blade.php under resources/views and add the following html markup.

After you create the view, you can access it by http://localhost/groceries. You should see a basic table with an entry.

<!doctype html>
  <html lang="en">
      <!-- Required meta tags -->
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

      <!-- Bootstrap CSS -->
      <link rel="stylesheet" href="" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">

      <title>Hello, world!</title>
      <div class="container mt-4 mb-4">
        <div class="row">
          <div class="col-md">
            <table class="table table-bordered table-striped">
                  <th scope="col">#</th>
                  <th scope="col">Title</th>
                  <th scope="col">Category</th>
                  <td scope="row">1</td>
                  <td scope="row">Apple</td>
                  <td scope="row">Fruits</td>

      <!-- Optional JavaScript -->
      <!-- jQuery first, then Popper.js, then Bootstrap JS -->
      <script src="" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo= " crossorigin="anonymous"></script>
      <script src="" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
      <script src="" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
      <script type="text/javascript">



Step 7: Extend the GroceryController

We no longer want to just get a JSON response. Tables are based on rows and columns, so let’s prepare the grocery data inside the controller like this. This is the easiest way to prepare data so that it can be output directly in the table.

public function index() {
  $html = "";

  // Load all columns in descending order based on the 'id' column
  $groceries = Grocery::orderBy('id', "desc')→get();

  // Loop result
  foreach($groceries as $grocerie)
    // Concatenate variable
    $html .= '
        <td scope="row">'. $grocerie->id .'</td>
        <td scope="row">'. $grocerie->title .'</td>
        <td scope="row">'. $grocerie->category .'</td>
  // Return data as HTML
  return response()->json($html);


Step 8: Do Ajax request

Fill the empty <script> at the end of the page with the following code:



  function getGroceryData() {
      method: 'GET',
      url: '/groceries/get',
      dataType: 'json',
      success: function(data) {
      error: function(error) {



  • The code in the $(document).ready(function(){ … }) function is available after the web page has been loaded successfully.
  • The groceryData function contains our ajax request which retrieves the grocery data.
  • In the function a call is made using ajax ($.ajax({ … })):
    • method: the type of HTTP-Request we send.
    • url: the api URL, according to the route in the web.php file.
    • dataType: data is sent to api as JSON.
    • success:  this codeblock is called if the request was successfull. In the next step, we will define the code here that will fill the table.
    • error: in this block we can define what should happen, if the request failed.


Step 9: Output retrieved data

Remember: What we get from the controller through the ajax request is pre-formatted HTMLthat we can immediately outpit in the table. All we have to do is add one line of code to our existing script inside the success block.



  function getGrocerieData() {
    method: 'GET',
    url: '/groceries/get',
    dataType: 'json',
    success: function(data) {
      // console.log(data);
    error: function(error) {


Ready! If we access the app via the url http://localhost:8000/groceries, we should see the table with three entries.

Laravel Ajax final table

Learn more about Laravel development by reading my related posts on the topic, for example How to upload images using Laravel and Intervention Image.