Laravel 5 AngularJS Tutorial

Introduction

In this tutorial, we are going to create a simple CREATE, READ, UPDATE, and DELETE CRUD application. We will use Laravel 5 for the backend and AngularJS for the front end. In accordance with the laws of beauty, we will use twitter bootstrap to add beauty to our simple application.
AngularJS is a powerful JavaScript client-side Model-View-Controller (MVC) framework. It is especially popular for building single page applications that behaviour like AJAX application. We will soon publish tutorial series on AngularJS. Subscribe to our free newsletter to get updates delivered to your mailbox when we publish the tutorial series on AngularJS.
This tutorial assumes you are familiar with basics of Laravel 5, have Apache, MySQL, PHP, Composer and optionally Bower installed.
Use composer here

Topics to be covered

We will cover the following topics in this tutorial.
  • Laravel 5 AngularJS backend (REST API)
  • AngularJS application structure
  • AngularJS app.js
  • AngularJS controllers employees.js
  • Displaying data from the REST API using AngularJS
  • AngularJS form validation

Laravel 5 AngularJS backend (REST API)

In this section, we will create a Laravel 5 application, database table using migrations and a simple REST API that will perform the CRUD operations. Let’s get our hands dirty.

Step 1: Create new Laravel 5 Application

Open the command prompt or terminal and browser to the root of the web server. On windows assuming you have XAMPP installed to drive C, run the following command
cd C:\xampp\htdocs
The above command browsers to the root directory Run the following command to create a new Laravel project using composer.
composer create-project laravel/laravel angulara
HERE,
  • the above code creates a new project in htdocs named angulara

Step 2: Database migrations

We first need to set the database configuration for our application
Open .env file in the project root
Set the database configurations as shown below
DB_HOST=localhost
DB_DATABASE=angulara
DB_USERNAME=root
DB_PASSWORD=melody
Save the changes
Note: use the database name, username and password that match the ones you have on your machine.
Run the following script in MySQL to create angulara database
CREATE DATABASE `angulara`;
We will now use the artisan command to create a migration file that will create a table for employee records.
Run the following artisan command to install the migration table in our database.
php artisan migrate:install
You will get the following message
Migration table created successfully
Run the following artisan command to create a migration file
php artisan make:migration create_employees_table
You will get the following message
Created migration: 2015_09_03_082733 _create_employees_table
Let’s now modify the newly created migration file
Open /database/migrations/20150903082733 createemployeestable
Modify the contents to the following
<?php

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

class CreateEmployeesTable extends Migration {

    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up() {
        Schema::create('employees', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name')->unique();
            $table->string('email')->unique();
            $table->string('contact_number');
            $table->string('position');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down() {
        Schema::drop('employees');
    }

}
Save the changes.
Run the following artisan command to run the migration
php artisan migrate
You will get the following messages
Migrated: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_100000_create_password_resets_table
Migrated: 2015_09_03_082733_create_employees_table
Check your database in MySQL. You should have an employees table created.

Step 3: Simple REST API

Let’s now create a controller for our REST API.
Run the following artisan command
php artisan make:controller Employees
You will get the following message
Controller created successfully.
Let’s now create an Eloquent ORM model for our REST API
1
php artisan make:model Employee
You will get the following message
Model created successfully.
Let’s now add a fillable array to our model Open Employee.php controller in /app/Employee.php
Modify the code to the following
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Employee extends Model
{
   protected $fillable = array('id', 'name', 'email','contact_number','position');
}
Let’s now modify the controller code
Open Employees.php in /app/Http/Controllers/Employees.php
Update the code to the following
<?php

namespace App\Http\Controllers;

use App\Employee;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;

class Employees extends Controller {

    /**
     * Display a listing of the resource.
     *
     * @return Response
     */
    public function index($id = null) {
        if ($id == null) {
            return Employee::orderBy('id', 'asc')->get();
        } else {
            return $this->show($id);
        }
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  Request  $request
     * @return Response
     */
    public function store(Request $request) {
        $employee = new Employee;

        $employee->name = $request->input('name');
        $employee->email = $request->input('email');
        $employee->contact_number = $request->input('contact_number');
        $employee->position = $request->input('position');
        $employee->save();

        return 'Employee record successfully created with id ' . $employee->id;
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return Response
     */
    public function show($id) {
        return Employee::find($id);
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  Request  $request
     * @param  int  $id
     * @return Response
     */
    public function update(Request $request, $id) {
        $employee = Employee::find($id);

        $employee->name = $request->input('name');
        $employee->email = $request->input('email');
        $employee->contact_number = $request->input('contact_number');
        $employee->position = $request->input('position');
        $employee->save();

        return "Sucess updating user #" . $employee->id;
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return Response
     */
    public function destroy(Request $request) {
        $employee = Employee::find($request->input('id'));

        $employee->delete();

        return "Employee record successfully deleted #" . $request->input('id');
    }
} 
We now need to define the routes for our REST API
Open /app/Http/routes.php
Modify the code to the following

<?php

/*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
|
| Here is where you can register all of the routes for an application.
| It's a breeze. Simply tell Laravel the URIs it should respond to
| and give it the controller to call when that URI is requested.
|
*/

Route::get('/', function () {
    return view('index');
});

Route::get('/api/v1/employees/{id?}', 'Employees@index');
Route::post('/api/v1/employees', 'Employees@store');
Route::post('/api/v1/employees/{id}', 'Employees@update');
Route::delete('/api/v1/employees/{id}', 'Employees@destroy');
That was it for our REST API. Let’s now create the frontend using AngularJS

AngularJS application structure

Our application will have the following structure
Use composer here
HERE,
  • app – contains all AngularJS related JavaScript files
  • app/controllers – contains all AngularJS controllers
  • app/lib – this directory will contain all AngularJS core files. You can also load AngularJS from a CDN network.
  • css – contains all CSS files
  • js – contains all regular JavaScript files for our UI.
Create the directories as shown in the above image

AngularJS app.js

This file will be used to define our application
Create a new file /public/app/app.js
Add the following code to it

var app = angular.module('employeeRecords', [])
        .constant('API_URL', 'http://localhost/angulara/public/api/v1/');
HERE,
  • var app = angular.module('employeeRecords', []) creates an AngularJS module and assigns the object to the variable app. All AngularJS files will be reference the variable app
  • .constant('API_URL', 'http://localhost/angulara/public/api/v1/'); defines a constant variable with the API URL.

AngularJS controllers employees.js

This is the file that will be responsible for interacting with our API
Create a new file /public/app/controllers/employees.js
Add the following code to it
app.controller('employeesController', function($scope, $http, API_URL) {
    //retrieve employees listing from API
    $http.get(API_URL + "employees")
            .success(function(response) {
                $scope.employees = response;
            });
    
    //show modal form
    $scope.toggle = function(modalstate, id) {
        $scope.modalstate = modalstate;

        switch (modalstate) {
            case 'add':
                $scope.form_title = "Add New Employee";
                break;
            case 'edit':
                $scope.form_title = "Employee Detail";
                $scope.id = id;
                $http.get(API_URL + 'employees/' + id)
                        .success(function(response) {
                            console.log(response);
                            $scope.employee = response;
                        });
                break;
            default:
                break;
        }
        console.log(id);
        $('#myModal').modal('show');
    }

    //save new record / update existing record
    $scope.save = function(modalstate, id) {
        var url = API_URL + "employees";
        
        //append employee id to the URL if the form is in edit mode
        if (modalstate === 'edit'){
            url += "/" + id;
        }
        
        $http({
            method: 'POST',
            url: url,
            data: $.param($scope.employee),
            headers: {'Content-Type': 'application/x-www-form-urlencoded'}
        }).success(function(response) {
            console.log(response);
            location.reload();
        }).error(function(response) {
            console.log(response);
            alert('This is embarassing. An error has occured. Please check the log for details');
        });
    }

    //delete record
    $scope.confirmDelete = function(id) {
        var isConfirmDelete = confirm('Are you sure you want this record?');
        if (isConfirmDelete) {
            $http({
                method: 'DELETE',
                url: API_URL + 'employees/' + id
            }).
                    success(function(data) {
                        console.log(data);
                        location.reload();
                    }).
                    error(function(data) {
                        console.log(data);
                        alert('Unable to delete');
                    });
        } else {
            return false;
        }
    }
});
HERE,
  • app.controller('employeesController', function($scope, $http, APIURL){…} defines a controller employeesController in the app variable that we created in /app/app.js. We have injected $scope, $http, and a contant APIURL as dependencies
  • $http.get(APIURL + "employees").success(function(response) {$scope.employees = response;}); uses Angular $http to call the API. APIURL + "employees" is passed as a parameter to $http. If the call is successful, the response to passed to .success anonymous function. The anonymous function assigns the response to $scope.employees variable. The $scope.employees variable will be available in our view.
  • $scope.toggle = function(modalstate, id) {} displays the modal form
  • $scope.save = function(modalstate, id){} saves a new record / updates an existing record
  • $scope.confirmDelete = function(id){} deletes an existing record

Displaying data from the REST API using AngularJS

We will now create a view that displays the data from the REST API. Both blade template and AngularJS use double curly braces to display data. In order to avoid conflicts between the two, we will not save the view as a blade template. It will be a regular view.
Create a new file in /resources/views/index.php
Add the following code
<!DOCTYPE html>
<html lang="en-US" ng-app="employeeRecords">
    <head>
        <title>Laravel 5 AngularJS CRUD Example</title>

        <!-- Load Bootstrap CSS -->
        <link href="<?= asset('css/bootstrap.min.css') ?>" rel="stylesheet">
    </head>
    <body>
        <h2>Employees Database</h2>
        <div  ng-controller="employeesController">

            <!-- Table-to-load-the-data Part -->
            <table class="table">
                <thead>
                    <tr>
                        <th>ID</th>
                        <th>Name</th>
                        <th>Email</th>
                        <th>Contact No</th>
                        <th>Position</th>
                        <th><button id="btn-add" class="btn btn-primary btn-xs" ng-click="toggle('add', 0)">Add New Employee</button></th>
                    </tr>
                </thead>
                <tbody>
                    <tr ng-repeat="employee in employees">
                        <td>{{  employee.id }}</td>
                        <td>{{ employee.name }}</td>
                        <td>{{ employee.email }}</td>
                        <td>{{ employee.contact_number }}</td>
                        <td>{{ employee.position }}</td>
                        <td>
                            <button class="btn btn-default btn-xs btn-detail" ng-click="toggle('edit', employee.id)">Edit</button>
                            <button class="btn btn-danger btn-xs btn-delete" ng-click="confirmDelete(employee.id)">Delete</button>
                        </td>
                    </tr>
                </tbody>
            </table>
            <!-- End of Table-to-load-the-data Part -->
            <!-- Modal (Pop up when detail button clicked) -->
            <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
                <div class="modal-dialog">
                    <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">{{form_title}}</h4>
                        </div>
                        <div class="modal-body">
                            <form name="frmEmployees" class="form-horizontal" novalidate="">

                                <div class="form-group error">
                                    <label for="inputEmail3" class="col-sm-3 control-label">Name</label>
                                    <div class="col-sm-9">
                                        <input type="text" class="form-control has-error" id="name" name="name" placeholder="Fullname" value="{{name}}" 
                                        ng-model="employee.name" ng-required="true">
                                        <span class="help-inline" 
                                        ng-show="frmEmployees.name.$invalid && frmEmployees.name.$touched">Name field is required</span>
                                    </div>
                                </div>

                                <div class="form-group">
                                    <label for="inputEmail3" class="col-sm-3 control-label">Email</label>
                                    <div class="col-sm-9">
                                        <input type="email" class="form-control" id="email" name="email" placeholder="Email Address" value="{{email}}" 
                                        ng-model="employee.email" ng-required="true">
                                        <span class="help-inline" 
                                        ng-show="frmEmployees.email.$invalid && frmEmployees.email.$touched">Valid Email field is required</span>
                                    </div>
                                </div>

                                <div class="form-group">
                                    <label for="inputEmail3" class="col-sm-3 control-label">Contact Number</label>
                                    <div class="col-sm-9">
                                        <input type="text" class="form-control" id="contact_number" name="contact_number" placeholder="Contact Number" value="{{contact_number}}" 
                                        ng-model="employee.contact_number" ng-required="true">
                                    <span class="help-inline" 
                                        ng-show="frmEmployees.contact_number.$invalid && frmEmployees.contact_number.$touched">Contact number field is required</span>
                                    </div>
                                </div>

                                <div class="form-group">
                                    <label for="inputEmail3" class="col-sm-3 control-label">Position</label>
                                    <div class="col-sm-9">
                                        <input type="text" class="form-control" id="position" name="position" placeholder="Position" value="{{position}}" 
                                        ng-model="employee.position" ng-required="true">
                                    <span class="help-inline" 
                                        ng-show="frmEmployees.position.$invalid && frmEmployees.position.$touched">Position field is required</span>
                                    </div>
                                </div>

                            </form>
                        </div>
                        <div class="modal-footer">
                            <button type="button" class="btn btn-primary" id="btn-save" ng-click="save(modalstate, id)" ng-disabled="frmEmployees.$invalid">Save changes</button>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <!-- Load Javascript Libraries (AngularJS, JQuery, Bootstrap) -->
        <script src="<?= asset('app/lib/angular/angular.min.js') ?>"></script>
        <script src="<?= asset('js/jquery.min.js') ?>"></script>
        <script src="<?= asset('js/bootstrap.min.js') ?>"></script>
        
        <!-- AngularJS Application Scripts -->
        <script src="<?= asset('app/app.js') ?>"></script>
        <script src="<?= asset('app/controllers/employees.js') ?>"></script>
    </body>
</html>
HERE,
  • <html lang="en-US" ng-app="employeeRecords"> ng-app="employeeRecords" attached our AngularJS application to the html tag. This will give it control over all elements in html tag.
  • <div ng-controller="employeesController"> links the div to the employeesController. This will make available all of the functions under employeesController to this div.
  • <tr ng-repeat="employee in employees"> used the AngularJS directive ng-repeat to loop through the results of the collection variable employees. ng-repeat is similar to the foreach loop.
Load the following URL in your web browser
1
http://localhost/angulara/public/
You will get the following
Use composer here
Click on Add New Employee button
You will get the following modal form
Use composer here
Click on Save changes
You will list the following list
Use composer here
Add more employees, edit existing record and even delete some
Use the comments section below if you get any errors. Our team will respond to you.

AngularJS form validation

AngularJS simplifies the process of validating forms.
Locate the code for the form and have a look at it
HERE,
  • <form name="frmEmployees" class="form-horizontal" novalidate=""> defines a form frmEmployees and add the novalidate attribute to stop HTML5 from validating our form
  • <input type ng-model="employee.name" ng-required="true"> ng-model is used for data binding. For example, anything entered in name text box is made available to employee.name variable. When AngularJS changes the value of employee.name, it is made available to the textbox too. ng-required= "true" validates our form and checks if a value has been supplied. If no value is supplied, a glass of $invalid is added to our form
  • <span class="help-inline" ng-show="frmEmployees.name.$invalid && frmEmployees.name.$touched">Name field is required ng-show only displays this element if the name text box has an invalid class
  • ng-disabled="frmEmployees.$invalid" disables the submit button if the form has an invalid class. If the user enters all required details in the correct format, the submit button is enabled.

Summary

AngularJS is a powerful client-side MVC framework that simplifies developing frontend parts of a web applications. Subscribe to our free newsletter and we will let you know when we publish tutorial series on AngularJS.

What’s next?

If you found this tutorial useful, use the social media buttons below to spread the word. If you didn’t find it useful, use the comments section below to let us know how we can improve it. Thanks for your support in advance.
Powered by Blogger.