Building a To-do List with Ajax

Exclusive offer: get 50% off this eBook here
Laravel Application Development Blueprints

Laravel Application Development Blueprints — Save 50%

Learn to develop 10 fantastic applications with the new and improved Laravel 4 with this book and ebook

$26.99    $13.50
by Arda Kılıçdağı Halil İbrahim Yılmaz | November 2013 | Open Source Web Development

In this article by Arda Kılıçdağı and Halil İbrahim Yılmaz, authors of Laravel Application Development Blueprints, we will cover the following:

  • Creating and migrating TO-DO list's database
  • Creating a TO-DO list's model
  • Creating the template
  • Inserting data to the database with Ajax
  • Retrieving the list from the database
  • How to allow only Ajax requests

(For more resources related to this topic, see here.)

Creating and migrating our to-do list's database

As you know, migrations are very helpful to control development steps. We'll use migrations in this article.

To create our first migration, type the following command:

php artisan migrate:make create_todos_table --table=todos --create

When you run this command, Artisan will generate a migration to generate a database table named todos.

Now we should edit the migration file for the necessary database table columns. When you open the folder migration in app/database/ with a file manager, you will see the migration file under it.

Let's open and edit the file as follows:

<?php use Illuminate\Database\Migrations\Migration; class CreateTodosTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('todos', function(Blueprint $table){ $table->create(); $table->increments("id"); $table->string("title", 255); $table->enum('status', array('0', '1'))->default('0'); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::drop("todos"); } }

To build a simple TO-DO list, we need five columns:

  • The id column will store ID numbers of to-do tasks
  • The title column will store a to-do task's title
  • The status column will store statuses of the tasks
  • The created_at and updated_at columns will store the created and updated dates of tasks

If you write $table->timestamps() in the migration file, Laravel's migration class automatically creates created_at and updated_at columns. As you know, to apply migrations, we should run the following command:

php artisan migrate

After the command is run, if you check your database, you will see that our todos table and columns have been created. Now we need to write our model.

Creating a todos model

To create a model, you should open the app/models/ directory with your file manager. Create a file named Todo.php under the directory and write the following code:

<?php class Todo extends Eloquent { protected $table = 'todos'; }

Let's examine the Todo.php file.

As you see, our Todo class extends an Eloquent model, which is the ORM (Object Relational Mapper) database class of Laravel.

The protected $table = 'todos'; code tells Eloquent about our model's table name. If we don't set the table variable, Eloquent accepts the plural version of the lower case model name as table name. So this isn't required technically.

Now, our application needs a template file, so let's create it.

Creating the template

Laravel uses a template engine that is called blade for static and application template files. Laravel calls the template files from the app/views/ directory, so we need to create our first template under this directory.

  1. Create a file with the name index.blade.php.
  2. The file contains the following code:

    <html> <head> <title>To-do List Application</title> <link rel="stylesheet" href="assets/css/style.css"> <!--[if lt IE 9]><script src = "//html5shim.googlecode.com/svn/trunk/html5.js"> </script><![endif]--> </head> <body> <div class="container"> <section id="data_section" class="todo"> <ul class="todo-controls"> <li><img src = "/assets/img/add.png" width="14px" onClick="show_form('add_task');" /></li> </ul> <ul id="task_list" class="todo-list"> @foreach($todos as $todo) @if($todo->status) <li id="{{$todo->id}}" class="done"> <a href="#" class="toggle"></a> <span id="span_{{$todo->id}}">{ {$todo->title}}</span> <a href="#" onClick="delete_task('{{$todo->id}}');" class="icon-delete">Delete</a> <a href="#" onClick="edit_task('{{$todo->id}}', '{{$todo->title}}');" class="icon-edit">Edit</a></li> @else <li id="{{$todo->id}}"><a href="#" onClick="task_done('{{$todo->id}}');" class="toggle"></a> <span id="span_{ {$todo->id}}">{{$todo->title}}</span> <a href="#" onClick="delete_task('{ {$todo->id}}');" class= "icon-delete">Delete</a> <a href="#" onClick="edit_task('{ {$todo->id}}','{{$todo->title}}');" class="icon-edit">Edit</a></li> @endif @endforeach </ul> </section> <section id="form_section"> <form id="add_task" class="todo" style="display:none"> <input id="task_title" type="text" name="title" placeholder="Enter a task name" value=""/> <button name="submit">Add Task</button> </form> <form id="edit_task" class="todo" style="display:none"> <input id="edit_task_id" type="hidden" value="" /> <input id="edit_task_title" type="text" name="title" value="" /> <button name="submit">Edit Task</button> </form> </section> </div> <script src = "http://code.jquery.com/ jquery-latest.min.js"type="text/javascript"></script> <script src = "assets/js/todo.js" type="text/javascript"></script> </body> </html>

The preceding code may be difficult to understand if you're writing a blade template for the first time, so we'll try to examine it. You see a foreach loop in the file. This statement loops our todo records.

We will provide you with more knowledge about it when we are creating our controller in this article.

If and else statements are used for separating finished and waiting tasks. We use if and else statements for styling the tasks.

We need one more template file for appending new records to the task list on the fly. Create a file with the name ajaxData.blade.php under app/views/ folder. The file contains the following code:

@foreach($todos as $todo) <li id="{{$todo->id}}"><a href="#" onClick="task_done('{{$todo- >id}}');" class="toggle"></a> <span id="span_{{$todo >id}}">{{$todo->title}}</span> <a href="#" onClick="delete_task('{{$todo->id}}');" class="icon delete">Delete</a> <a href="#" onClick="edit_task('{{$todo >id}}','{{$todo->title}}');" class="icon-edit">Edit</a></li> @endforeach

Also, you see the /assets/ directory in the source path of static files. When you look at the app/views directory, there is no directory named assets. Laravel separates the system and public files. Public accessible files stay under your public folder in root. So you should create a directory under your public folder for asset files.

We recommend working with these types of organized folders for developing tidy and easy-to-read code. Finally you see that we are calling jQuery from its main website. We also recommend this way for getting the latest, stable jQuery in your application.

You can style your application as you wish, hence we'll not examine styling code here. We are putting our style.css files under /public/assets/css/.

For performing Ajax requests, we need JavaScript coding. This code posts our add_task and edit_task forms and updates them when our tasks are completed. Let's create a JavaScript file with the name todo.js in /public/assets/js/. The files contain the following code:

function task_done(id){ $.get("/done/"+id, function(data) { if(data=="OK"){ $("#"+id).addClass("done"); } }); } function delete_task(id){ $.get("/delete/"+id, function(data) { if(data=="OK"){ var target = $("#"+id); target.hide('slow', function(){ target.remove(); }); } }); } function show_form(form_id){ $("form").hide(); $('#'+form_id).show("slow"); } function edit_task(id,title){ $("#edit_task_id").val(id); $("#edit_task_title").val(title); show_form('edit_task'); } $('#add_task').submit(function(event) { /* stop form from submitting normally */ event.preventDefault(); var title = $('#task_title').val(); if(title){ //ajax post the form $.post("/add", {title: title}).done(function(data) { $('#add_task').hide("slow"); $("#task_list").append(data); }); } else{ alert("Please give a title to task"); } }); $('#edit_task').submit(function() { /* stop form from submitting normally */ event.preventDefault(); var task_id = $('#edit_task_id').val(); var title = $('#edit_task_title').val(); var current_title = $("#span_"+task_id).text(); var new_title = current_title.replace(current_title, title); if(title){ //ajax post the form $.post("/update/"+task_id, {title: title}).done(function(data) { $('#edit_task').hide("slow"); $("#span_"+task_id).text(new_title); }); } else{ alert("Please give a title to task"); } });

Let's examine the JavaScript file.

Laravel Application Development Blueprints Learn to develop 10 fantastic applications with the new and improved Laravel 4 with this book and ebook
Published: November 2013
eBook Price: $26.99
Book Price: $44.99
See more
Select your format and quantity:

Inserting data to a database with Ajax

In this application, we use the Ajax POST method for inserting data to the database. jQuery is the best JavaScript framework for these kind of applications. jQuery also comes with powerful selector functions.

We have two forms in our HTML code, so we need to post them with Ajax to insert or update the data. We'll do it with jQuery's post method.

We'll serve our JavaScript files under /public/assets/js, so let's create a todo.js file under this directory. First we need a request to add new tasks. The JavaScript code contains the following code:

$('#add_task').submit(function(event) { /* stop form from submitting normally */ event.preventDefault(); var title = $('#task_title').val(); if(title){ //ajax post the form $.post("/add", {title: title}).done(function(data) { $('#add_task').hide("slow"); $("#task_list").append(data); }); } else{ alert("Please give a title to task"); } });

This code posts our add_task form to the server if the user doesn't forget to provide a title to task. If the user forgets to provide a title to the task, the code does not post the form. After it is posted, the code will hide the form and append the task list with a new record. Meanwhile, we will be waiting for the response to get the data.

So we need a second form to update a task's title. The code will update the task's title and change the text of updated records via Ajax on-the-fly. On-the-fly programming (or live coding) is a style of programming in which the programmer/performer/composer augments and modifies the program while it is running, without stopping or restarting, in order to assert expressive, programmable control for performance, composition, and experimentation at runtime. Because of the fundamental powers of programming languages, we believe the technical and aesthetic aspects of on-the-fly programming are worth exploring in web applications. The update form's code should be as follows:

$('#edit_task').submit(function(event) { /* stop form from submitting normally */ event.preventDefault(); var task_id = $('#edit_task_id').val(); var title = $('#edit_task_title').val(); var current_title = $("#span_"+task_id).text(); var new_title = current_title.replace(current_title, title); if(title){ //ajax post the form $.post("/update/"+task_id, {title: title}).done(function(data) { $('#edit_task').hide("slow"); $("#span_"+task_id).text(new_title); }); } else{ alert("Please give a title to task"); } });

Laravel has the RESTful controller feature. This means you can define the routes' and controller functions' RESTful base. Also, routes can be defined for different request types such as POST, GET, PUT, or DELETE.

Before defining the routes, we need to code our controller. The controller files stay under app/controllers/; create a file in it named TodoController.php. The controller code should be as follows:

<?php class TodoController extends BaseController { public $restful = true; public function postAdd() { $todo = new Todo(); $todo->title = Input::get("title"); $todo->save(); $last_todo = $todo->id; $todos = Todo::whereId($last_todo)->get(); return View::make("ajaxData") ->with("todos", $todos); } public function postUpdate($id) { $task = Todo::find($id); $task->title = Input::get("title"); $task->save(); return "OK"; } }

Let's examine the code.

As you see in the code, RESTful functions defines syntaxes such as postFunction, getFunction, putFunction, or deleteFunction.

We have two post forms, so we need two POST functions and one GET method to get records from the database and show them in the template in the foreach statement to the visitor.

Let's examine the postUpdate() method in the preceding code:

public function postUpdate($id) { $task = Todo::find($id); $task->title = Input::get("title"); $task->save(); return "OK"; }

The following points explain the preceding code:

  • The method needs a record called id to update. The route where we post would be like /update/record_id.
  • $task = Todo::find($id); is that part of the method which finds the record from the database which has the given id.
  • $task->title = Input::get("title"); means get the value of the form element named title and updating the title column record as the posted value.
  • $task->save(); applies the changes and runs the update query on the database server.

Let's examine the postAdd() method. This method works like our getIndex() method. The first part of the code creates a new record on the database server:

public function postAdd() { $todo = new Todo(); $todo->title = Input::get("title"); $todo->save(); $last_todo = $todo->id; $todos = Todo::whereId($last_todo)->get(); return View::make("ajaxData") ->with("todos", $todos); }

The following points explain the preceding code:

  • The code line $last_todo = $todo->id; gets the ID of this record. It is equivalent to the mysql_insert_id() function.
  • The code line $todos = Todo::whereId($last_todo)->get(); fetches the record from todo table which has an id column equal to $last_todo variable.
  • The code line View::make("ajaxData") ->with("todos", $todos); is very important to understand Laravel's view mechanism:
    • The code line View::make("ajaxData") refers to our template file. Do you remember the ajaxData.blade.php file, which we created under /app/views/? The code calls this file.
    • The code line ->with("todos", $todos); assigns the last record to the template file as a variable named todos (the first parameter). So, we can show the last record in the template file with the foreach loop.

Retrieving the list from a database

We also need a method for getting the existing data from our database server. In our controller file, we need the function as shown in the following code:

public function getIndex() { $todos = Todo::all(); return View::make("index") ->with("todos", $todos); }

Let's examine the getIndex() method:

  • In the code, $todos = Todo:all() means get all records from the database and assign them to the $todos variable.
  • In the code, View::make("index") defines our template file. Did you remember the index.blade.php file, which we created under /app/views/? The code calls this file.
  • In the code, ->with("todos", $todos); assigns the records to the template file. So, we can show the records in the template file with the foreach loop.

Finally, we will define our routes. For defining routes, you should open the routes.php file in the apps folder. Laravel has a great feature for defining routes named the RESTful controller. You can define all the routes with a single line of code as follows:

Route::controller('/', 'TodoController');

The preceding code assigns all the applications' root-based requests to the TodoController function. If you need, you can also define the routes manually as follows:

Route::method('path/{variable}', 'TheController@functionName');

How to allow only Ajax requests

Our application accepts all POST and GET requests even without Ajax. But we just need to allow an Ajax request for add and update functions. Laravel's Request class provides many methods for examining the HTTP request for your applications. One of these functions is named ajax(). We can check the request type under controllers or route filters.

Allowing the request using route filters

Route filters provide a convenient way of limiting, accessing, or filtering the requests to a given route. There are several filters included in Laravel, which are located in the filters.php file in the app folder. We can define our custom filter under this file. The route filter for an Ajax request should be as shown in the following code:

Route::filter('ajax_check', function() { if (Request::ajax()) { return true; } });

Attaching a filter to a route is also very easy. Check the sample route shown in the following code:

Route::get('/add', array('before' => 'ajax_check', function() { return 'The Request is AJAX!'; }));

In the preceding example, we defined a route filter to the route with the before variable. This means, our application first checks the request type and then calls the controller function and passes the data.

Allowing the request using the controller side

We can check for the request type under controller. We'll use this method in this section. This method is useful for function-based filtering. For doing this, we should change our add and update functions as shown in the following code:

public function postAdd() { if(Request::ajax()){ $todo = new Todo(); $todo->title = Input::get("title"); $todo->save(); $last_todo = $todo->id; $todos = Todo::whereId($last_todo)->get(); return View::make("ajaxData") ->with("todos", $todos); } } public function postUpdate($id) { if(Request::ajax()){ $task = Todo::find($id); $task->title = Input::get("title"); $task->save(); return "OK"; } }

Wrapping up

During the article, we coded to add a new task, updated it, and listed the tasks. We also need to update the statuses and delete the tasks. For doing that, we need two functions that are called getDone() and getDelete(). As you know from previous sections of this article, these functions are RESTful and accepts GET method requests. So, our function should be as shown in the following code:

public function getDelete($id) { if(Request::ajax()){ $todo = Todo::whereId($id)->first(); $todo->delete(); return "OK"; } } public function getDone($id) { if(Request::ajax()){ $task = Todo::find($id); $task->status = 1; $task->save(); return "OK"; } }

We also need to update the todo.js file. The final JavaScript code should be as shown in the following code:

function task_done(id){ $.get("/done/"+id, function(data) { if(data=="OK"){ $("#"+id).addClass("done"); } }); } function delete_task(id){ $.get("/delete/"+id, function(data) { if(data=="OK"){ var target = $("#"+id); target.hide('slow', function(){ target.remove(); }); } }); } function show_form(form_id){ $("form").hide(); $('#'+form_id).show("slow"); } function edit_task(id,title){ $("#edit_task_id").val(id); $("#edit_task_title").val(title); show_form('edit_task'); } $('#add_task').submit(function(event) { /* stop form from submitting normally */ event.preventDefault(); var title = $('#task_title').val(); if(title){ //ajax post the form $.post("/add", {title: title}).done(function(data) { $('#add_task').hide("slow"); $("#task_list").append(data); }); } else{ alert("Please give a title to task"); } }); $('#edit_task').submit(function(event) { /* stop form from submitting normally */ event.preventDefault(); var task_id = $('#edit_task_id').val(); var title = $('#edit_task_title').val(); var current_title = $("#span_"+task_id).text(); var new_title = current_title.replace(current_title, title); if(title){ //ajax post the form $.post("/update/"+task_id, {title: title}).done(function(data) { $('#edit_task').hide("slow"); $("#span_"+task_id).text(new_title); }); } else{ alert("Please give a title to task"); } });

Summary

In this article we tried to understand how to use Ajax with Laravel. During the article, we used the basics of templating, request filtering, routing, and RESTful controllers. We also learned to update and delete data from our database.

Resources for Article:


Further resources on this subject:


Laravel Application Development Blueprints Learn to develop 10 fantastic applications with the new and improved Laravel 4 with this book and ebook
Published: November 2013
eBook Price: $26.99
Book Price: $44.99
See more
Select your format and quantity:

About the Author :


Arda Kılıçdağı

Arda Kılıçdağı is a PHP, MySQL, and JavaScript programmer from Turkey. He has been developing applications in PHP since 2005. He has been administrating the Turkish national support website for the well-known open source content management script, PHP-Fusion. He's also one of the international developers and a member of the management team for PHP-Fusion, and he has an important role in the project's future. He has worked as a developer and has experience on projects such as Begendy (an exclusive private shopping website) and Futbolkurdu (a local soccer news website). He is experienced in using the Facebook API, Twitter API, and PayPal's Adaptive Payments API (which is used on crowdfunding websites such as KickStarter). He's also experienced in using JavaScript, and he's currently infusing his applications with JavaScript and jQuery, both on the frontend and backend.

He has also developed applications using CodeIgniter and CakePHP for about four years, but these PHP frameworks didn't suit his needs completely. This is why he decided to use another framework for his projects, and that is when he met Laravel. Currently he is developing all his applications using Laravel.

He's also obsessed with Unix/Linux and uses Linux on a daily basis. In addition, he is administrating the world's best-known microcomputer, Raspberry Pi's biggest Turkish community website.

Halil İbrahim Yılmaz

Halil İbrahim Yılmaz is a Python and PHP programmer and an e-commerce consultant from Turkey. He has worked as a developer and a software coordinator in over a dozen ventures, including Begendy, Modeum, Futbolkurdu, Arkeoidea, and Uzmanlazim. He is experienced in using many APIs such as Google, YouTube, Facebook, Twitter, Grooveshark, and PayPal. After meeting his business partner, he co-founded 16 Pixel, a Bursa-based creative consultancy that specializes in web development and e-commerce.

He loves learning functional programming languages (Erlang and Haskell), new JavaScript technologies (Node.js), and NoSQL database systems (Riak and MongoDB). When he is not working on client projects, he is often trying to code a web application with those technologies.

He lives in a house full of Linux boxes in Bursa, Turkey.

Books From Packt


Laravel Starter [Instant]
Laravel Starter [Instant]

 Laravel Application Development Cookbook
Laravel Application Development Cookbook

RESTful PHP Web Services
RESTful PHP Web Services

 Learning PHP Data Objects
Learning PHP Data Objects

 Instant PHP Web Scraping [Instant]
Instant PHP Web Scraping [Instant]

 Magento 1.3: PHP Developer's Guide
Magento 1.3: PHP Developer's Guide

 PHP Programming with PEAR
PHP Programming with PEAR

Magento PHP Developer’s Guide
Magento PHP Developer’s Guide


Your rating: None Average: 4.5 (2 votes)

Post new comment

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
Q
m
d
5
S
n
Enter the code without spaces and pay attention to upper/lower case.
Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software