Mr. B.
Mr. B.

Reputation: 8717

AJAX: How to show/add/edit/delete (CRUD) as much performant as possible?

I would like to get a better performance for my scripts where the user is able to Create/Read/Update/Delete (CRUD) data.

Currently I send a request after every action and refresh the overview page. Example:

<a href="script.php?action=save">Add</a>
<table>
    <tr>
        <td>Item 1</td>
        <td>
            <a href="script.php?action=save&id=123">Edit</a>
            <a href="script.php?action=delete&id=123">Delete</a>
        </td>
<table>

-

<?php
// script.php -> action=delete
$error = true;
if ($this->database->query("DELETE FROM items WHERE id = :id", array("id" => $_GET["id"]))) {
    $error = false; 
}    

// forward back
header("Location: script.php?error=" . $error);
?>

I don't like it and would like to change it.

What do you think about this:

Pseudocode:

<script>
var items = null; // items
var items_deleted = null; // items, marked to delete
var items_updated = null; // items, marked to be updated

// builds the html table 
function build_html_table() {
    // sort the items
    items = sortTheItems(items);

    html  = "<table>";
    for (i = 0; i < items.length; i++):
        html += '<tr id="'+items[i].id+'">';
        html +=     '<td>'+items[i].name+'</td>';
        html +=     '<td>';
        html +=         '<a href="script.php?action=save&id='+items[i].id+'" class="edit">Edit</a>';
        html +=         '<a href="script.php?action=save&id='+items[i].id+'" class="delete">Delete</a>';
        html +=     '</td>';
        html += "</tr>";
    endfor;
    html += "</table>";

    $("#table").html(html);
}

// on clicking the delete-link
$(".delete").click(function() {
    // get id
    id = $(this).parent().parent().attr("id"); // id of <tr>

    // delete item (temp)
    for (i = 0; i < items.length; i++) 
        if (items[i].id == id) 
            unset(items[i]);
    endfor;

    // mark for deleting
    items_deleted.push(id);

    // re-build table
    build_html_table();
});

// on clicking the edit-link
$(".edit").click(function() {
    // get id
    id = $(this).parent().parent().attr("id");

    // get the item to edit
    item = null;
    for (i = 0; i < items.length; i++):
        if (items[i].id == id)
            item = items[i];
    endfor;

    // fill the save-form
    $("#save_dialog [name='id']").val(item.id);
    $("#save_dialog [name='name']").val(item.name);
    $("#save_dialog [name='content']").val(item.content);

    // open save-form in a dialog
    $("#save_dialog").dialog();
});

// on clicking the add link
$(".add").click(function() {
    // reset the save-form
    $("#save_dialog [name='id']").val("");
    $("#save_dialog [name='name']").val("");
    $("#save_dialog [name='content']").val("");

    // open save-form in a dialog
    $("#save_dialog").dialog();
});

// save form
$("#save_form").onSubmit(function() {
    id = $(this).find("[name='id']");
    if (!id) {
        // real add, getting the new id
        $(this).ajaxForm({
            onSuccess: function(responseText, $form) {
                item.id      = responseText; // script.php?action=save returns the last inserted/updated ID
                item.name    = $form.find("[name='name']");
                item.content = $form.find("[name='content']");

                // add the added item
                items.push(item);
        });            
    } else {
        // temp. update

        // update the old entry
        for (i = 0; i < items.length; i++):
            if (items[i].id == item.id) {
                items[i].name = $(this).find("[name='name']").val();
                items[i].content = $(this).find("[name='content']").val();

                // mark this item to update
                items_updated[items[i].id] = items[i];
            }
        endfor; 
    }

    // re-build table
    build_html_table();        
});

// doc ready
$(function() {
    // get the items data (json)
    items = getJSON("items_json.php");

    // build table
    build_html_table();
});

// on window close/unload (or after $x minutes)
$.unload(function() {
    // real delete 
    ajaxRequest("script.php?action=delete&ids=", items_deleted);

    // real update
    ajaxRequest("script.php?action=update", items_updated);
});
</script>

<a href="script.php?action=add" class="add">Add</a>
<div id="table">loading...</div>

<div id="save_dialog" class="hidden">
    <form action="script.php?action=save" method="POST" id="save_form">
        <input type="hidden" name="id"/>
        Name: <input type="text" name="name"/><br/>
        Content: <textarea name="content"></textarea><br/>
        <input type="submit"/>
    </form>
</div>

What do you think about my idea? What could I do better? Are there good jQuery-plugins to get this job done easily?

Thanks in advance!

Note: It's just pseudo-code!

Upvotes: 1

Views: 3306

Answers (1)

charlietfl
charlietfl

Reputation: 171698

A big helper is using data- attributes to save parsing other attributes to get things like ID, or action which you have hardcoded in url( keep there for no JS in page) but helpful to access it in handlers also.

 /* "data-arbitraryName" can be read using jQuery `data()` method*/
 html += '<tr id="'+items[i].id+'" data-id="'+items[i].id+'">';

/* add common class to "controls"*/
'<a href="script.php?action=save&id='+items[i].id+'" class="edit crud_btn" data-action="save">Edit</a>';


/* can now combine a lot in one click handler*/
$('#tableParent').on('click', '.crud_btn', function(e){

      var $btn=$(this), $row=$btn.closest('tr'), row_id= $row.data('id');
       /* data() method reads "data-" attributes*/
      var thisAction=$(this).data('action')
     /* create data object to send*/
     var dataToServer={/* this data always sent*/
          action: thisAction,
          id: row_id || 'add';
     }
      /* additional data as needed based on "action"*/
      if( thisAction == 'add'){
          $.extend( dataToServer, someFormData);
     }

     /* use direct file url, if GET, jQUery will append search string from dataToServer object*/
     $.getJSON('script.php', dataToServer, function(response){
          if( response.success ){  
              /* psuedo update method*/
               updatStoredData( response, action);
               /* success handling based on "action"*/
               if(thisAction=='delete'){
                   $row.remove();

               }
          }
    })
   return false;
})

Upvotes: 1

Related Questions