To-do lists are a great way to keep track of your daily tasks. In this tutorial, we will build our own to-do list using PHP, MySQL, and AJAX. This tutorial assumes that you have a basic understanding of HTML, PHP, MySQL, and JavaScript.

We will be using the following files throughout this tutorial. You can download them using the link below. Feel free to use an alternative structure, but remember to change your file paths from those in the example code.

View Demo    Download Files

Main Index File

The first thing we need to do is lay out the structure for our main index page (index.php). This application will only have one page and we will use AJAX to add and delete to-do items. Open the index.php file and add the following code.

<html>
<head>
    <title>Simple To-Do List</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div class="wrap">

    </div>
</body>
</html>

Note: For the sake of time, we will not cover styling in this tutorial. A CSS file has been included in the source files.

Connecting to the MySQL Database

We need to set up a MySQL database for storing our to-do items. The easiest way to do this is trough a server-side tool called phpMyAdmin. The tools comes pre-installed on most web hosts and is bundled with local development services such as WampServer and XAMPP. We will be setting up one table with the name of ‘tasks’ and the following columns in this order: ‘id’, ‘task’, ‘date’, ‘time’. Be sure to set the id column to auto-increment (there should be a checkbox labeled ‘A_I’).

phpMyAdmin Screenshot

After creating the new table, we need to connect our project to the database. Open connect.php and add the following code to the file. Be sure to substitute your database details for the ‘username’, ‘password’, and ‘database_name’ fields. Save the file when you are done.

<?php
    $server = "localhost";
    $db_user = "username";
    $db_pass = "password";
    $db_name = "database_name";

    mysql_connect($server, $db_user, $db_pass) or die("Could not connect to server!");
    mysql_select_db($db_name) or die("Could not connect to database!");
?>

Explaining the Code
PHP has a mysql_connect() function that creates a connection to the MySQL server. The server variable should remain set to ‘localhost’ unless your database is hosted on a different server than the project files. In that case, substitute this value for the MySQL server’s IP address. Once the connection has been made, the mysql_select_db() function selects a specific database from the server.

Now that we have created our connect.php file, we need to add it to the main index file. Add the following code to index.phpand save the change.

<html>
<head>
    <title>Simple To-Do List</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div class="wrap">
 <div class="task-list">
     <ul>
                <?php require("includes/connect.php"); ?>
     </ul>
 </div>
    </div>
</body>
</html>

Adding a New To-Do Item

The next thing we want to do is create a way to add items to our to-do list. To do this, we will use a form and submit the results to the database. Add the following <form>code to index.php and save the change.

<html>
<head>
    <title>Simple To-Do List</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div class="wrap">
 <div class="task-list">
     <ul>
                <?php require("includes/connect.php"); ?>
     </ul>
 </div>
  <form class="add-new-task" autocomplete="off">
      <input type="text" name="new-task" placeholder="Add a new item..." />
 </form>
    </div>
</body>
</html>

Note: Notice that the form does not have action and method attributes. These are typically used to submit data to another file via a post or get request. We will be using AJAX to submit our form, so we will not be defining either of these attributes. For more information on AJAX, check out this article from W3Schools.

Open index.php in your web browser and have a look. At this point, you should see a large white rectangle where the to-do items will be displayed and a text field for adding new items to the list.

PHP To-Do List Screenshot

We need to set up a way for the form to communicate with the database. Using jQuery, let’s send our new to-do item via a post request to the add-task.php file. From there, our item will be formatted and saved to the database. Add the following to the index.php file directly after the closing </body> tag.

<script src="https://code.jquery.com/jquery-latest.min.js"></script>
<script>
    add_task(); // Call the add_task function

    function add_task() {
        $('.add-new-task').submit(function(){
     var new_task = $('.add-new-task input[name=new-task]').val();

     if(new_task != ''){
   $.post('includes/add-task.php', { task: new_task }, function( data ) {
        $('.add-new-task input[name=new-task]').val('');
        $(data).appendTo('.task-list ul').hide().fadeIn();
                });
     }
     return false; // Ensure that the form does not submit twice
        });
    }
</script>

Explaining the Code
The script above intercepts the text field value on form submit and sends it to add-task.php using the $.post() jQuery method. The add-task.php file then sends back confirmation of the newly added item, so it can be added to the list. The beautiful thing is that all of this happens without refreshing the page!

Now that our form is sending the new to-do item to add-task.php, we need to tell that file what to do with the information. Open add-task.php and add the following code. Remember to save the file.

<?php 
    $task = strip_tags( $_POST['task'] );
    $date = date('Y-m-d'); // Today%u2019s date
    $time = date('H:i:s'); // Current time

    require("connect.php");

    mysql_query("INSERT INTO tasks VALUES ('', '$task', '$date', '$time')");

    $query = mysql_query("SELECT * FROM tasks WHERE task='$task' and date='$date' and time='$time'");

    while( $row = mysql_fetch_assoc($query) ){
 $task_id = $row['id'];
  $task_name = $row['task'];
    }

    mysql_close();

    echo '<li><span>'.$task_name.'</span><img id="'.$task_id.'" class="delete-button" width="10px" src="images/close.svg" /></li>';
?>

Explaining the Code
This file assigns the value of the text field to a PHP variable and creates two new variables: one for the current date and one for the time stamp. These fields will help us sort our items by date when they appear in the to-do list. Notice thestrip_tags() function which helps to remove code that may be added by a user attempting to hack your database. Next, we link to connect.php, so we can access the database and add the new values to the tasks table. Lastly, we fetch the new row from the database and print the related fields to a <li> element. We have already told jQuery to print this item in the task list once the item has been successfully added.

Displaying To-Do Items

So far we have created a form to enter new tasks, submitted the form data using AJAX, and saved the result to a MySQL database. Next, we must create a loop in the main index file that prints out each to-do item when the page loads. You might be wondering why we need to do this if jQuery is already printing newly added items. jQuery is only adding new items and not items that are currently in the database. These items must be fetched before the page loads via PHP. The new items are then added to the DOM as they are created.

Let’s crack open the index.php file and and the following code. Save the file when you are done.

<html>
<head>
    <title>Simple To-Do List</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div class="wrap">
  <div class="task-list">
     <ul>
<?php
    require("includes/connect.php");

    $query = mysql_query("SELECT * FROM tasks ORDER BY date ASC, time ASC");
    $numrows = mysql_num_rows($query);

    if($numrows>0){
  while( $row = mysql_fetch_assoc( $query ) ){

      $task_id = $row['id'];
      $task_name = $row['task'];

      echo '<li>
                    <span>'.$task_name.'</span>
        <img id="'.$task_id.'" class="delete-button" width="10px" src="images/close.svg" />
     </li>';
  }
    }
?>
     </ul>
 </div>
  <form class="add-new-task" autocomplete="off">
      <input type="text" name="new-task" placeholder="Add a new item..." />
 </form>
    </div>
</body>
<script src="https://code.jquery.com/jquery-latest.min.js"></script>
<script>
    add_task(); // Call the add_task function

    function add_task() {
        $('.add-new-task').submit(function(){
      var new_task = $('.add-new-task input[name=new-task]').val();

     if(new_task != ''){
   $.post('includes/add-task.php', { task: new_task }, function( data ) {
        $('.add-new-task input[name=new-task]').val('');
        $(data).appendTo('.task-list ul').hide().fadeIn();
                });
     }
     return false; // Ensure that the form does not submit twice
        });
    }
</script>
</html>

Explaining the Code
The code above connects to the database, selects every row ordered by date and time, and prints each to-do item inside of a<li> element. Take notice that the rows are sorted by both date and time. If we only sorted by date, your items would not display in the correct order.

Open your web browser and refresh the page. If you try adding a new item to the list it should fades into place.

Adding a new item to the to-do list

Deleting a To-Do Item

The last thing we need to do is allow a user to delete a to-do item from the list. You’ll notice that this process is similar to adding a new item. We will use the close image next to each item in the list to fire an event that removes that particular item. Let’s add the following code near the end of index.php and save our progress.

<html>
<head>
    <title>Simple To-Do List</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div class="wrap">
  <div class="task-list">
     <ul>
<?php
    require("includes/connect.php");

    $query = mysql_query("SELECT * FROM tasks ORDER BY date ASC, time ASC");
    $numrows = mysql_num_rows($query);

    if($numrows>0){
  while( $row = mysql_fetch_assoc( $query ) ){

      $task_id = $row['id'];
      $task_name = $row['task'];

      echo '<li>
                    <span>'.$task_name.'</span>
        <img id="'.$task_id.'" class="delete-button" width="10px" src="images/close.svg" />
     </li>';
  }
    }
?>
     </ul>
 </div>
  <form class="add-new-task" autocomplete="off">
      <input type="text" name="new-task" placeholder="Add a new item..." />
 </form>
    </div>
</body>
<script src="https://code.jquery.com/jquery-latest.min.js"></script>
<script>
    add_task(); // Call the add_task function
    delete_task(); // Call the delete_task function

    function add_task() {
        $('.add-new-task').submit(function(){
     var new_task = $('.add-new-task input[name=new-task]').val();

     if(new_task != ''){
   $.post('includes/add-task.php', { task: new_task }, function( data ) {
        $('.add-new-task input[name=new-task]').val('');
        $(data).appendTo('.task-list ul').hide().fadeIn();
                    delete_task();
                });
     }
     return false; // Ensure that the form does not submit twice
        });
    }

    function delete_task() {
        $('.delete-button').click(function(){
      var current_element = $(this);
      var id = $(this).attr('id');

      $.post('includes/delete-task.php', { task_id: id }, function() {
    current_element.parent().fadeOut("fast", function() { $(this).remove(); });
     });
        });
    }
</script>
</html>

Notice that each time the close.svg image is added to the DOM it is given a unique id. This id corresponds to the primary id field in the database for that particular task. It is the best way to communicate which item we want to delete.
Open delete-task.php and add the following code. Then save your work.

<?php 
    $task_id = strip_tags( $_POST['task_id'] );
    require("connect.php");
    mysql_query("DELETE FROM tasks WHERE id='$task_id'");
?>

Try deleting one of your to-do items from the list. It should disappear from the screen. Once the animation is finished, the item is removed from the DOM as well.

The finished to-do list

Conclusion

Hopefully, this tutorial has helped you understand more about how to use PHP and AJAX to build powerful web forms. You can take this example much further by adding hyperlink support to your items, allowing users to edit items, or creating additional lists. There are many possibilities and further exploration may lead to a better understanding of the concepts we covered. Have fun and let me know what you learn!

If you are having trouble with anything above, I have a working copy of the project on GitHub. It includes database file which you can import into your database.

https://github.com/mattlitzinger/Simple_AJAX_Todo_List

Did You Find This Helpful?

Join my biweekly digest of curated HTML, CSS and JavaScript news.

Matt Litzinger headshot

Matt Litzinger

Matt is a New Hampshire-based web developer focused on UX and digital accessibility.