skip to Main Content

I am working on a Register and Login application with CodeIgniter 3 and Twitter Bootstrap.

I have a “users” MySQL table and a corresponding “users.php” view that renders the “users” table in an HTML format, like the image below illustrates:

enter image description here

The “Actions” column in the Bootstrap table has, on each row, an “Enable” or “Disable” button, depending on the state of he user. The code for this part of the view is:

// Status column
<td>
   <?php if ($user->active == 1) {
    echo '<span class="text-success">' . 'Enabled' . '</span>';
    } else {
    echo '<span class="text-danger">' . 'Disabled' . '</span>';
    }
   ?>
</td>

// Enable/Disable buttons
<?php if ($user->active == 1) { ?>
    <a href="<?php echo base_url(); ?>users/deactivate/<?php echo $user->id ?>" title="Deactivate" class="btn btn-success btn-xs state-change" data-role="deactivate" data-id="<?php echo $user->id ?>"><span class="glyphicon glyphicon-ban-circle"></span> Disable</a>
<?php } else { ?>
   <a href="<?php echo base_url(); ?>users/activate/<?php echo $user->id ?>" title="Activate" class="btn btn-success btn-xs state-change" data-role="activate" data-id="<?php echo $user->id ?>"><span class="glyphicon glyphicon-ok"></span> Enable</a>
<?php } ?>

I activate/deactivate users without page refresh, via AJAX:

$('.state-change').on('click', function(evt) {
    evt.preventDefault();
    var id = $(this).data('id');
    var role = $(this).data('role');
    if (role == "activate") {
        var stateUrl = 'users/activate/';
    } else {
        var stateUrl = 'users/deactivate/';
    }
    $.ajax({
        url: stateUrl + id,
        method: 'GET',
        dataType: 'php',
        success: function(){
            console.log(id);
            console.log(role);
        }
    });
});

The problem is that the data regarding the state of the user does not come back to the view and the columns “Status” and “Actions” do not render correctly.

I wish I didn’t have to update the view “statically” from the success callback, with jQuery’s html() method or something similar.

function(){
    console.log(id);
    console.log(role);
    //change columns html here
}

What shall I do to update the view “dynamically”?

2

Answers


  1. You will need to use javascript to modify your table after you get the data back. Since you’re already using jQuery, you have tools to make that pretty simple.

    Your problem can be broken into two steps: Identify the right part of the page to update, and then modify the cells of interest.

    Identifying the right cells is simplified because the mouse event passed to your function includes a reference to the thing that was clicked.

    To make finding the right parts of the table easier, it’s good to give each <td> a class:

    // Status column
    <td class="status-column">
        // your php status stuff from above
    </td>
    
    // Button column
    <td class="activate-column">
        // your php button-drawing stuff from above
    </td>
    

    Now it will be easy to find what you’re looking for to modify.

    Here’s your ajax call with a few additions to redraw the cells in question:

    $('.state-change').on('click', function(evt) {
        evt.preventDefault();
        var id = $(this).data('id');
        var role = $(this).data('role');
        if (role == "activate") {
            var stateUrl = 'users/activate/';
        } else {
            var stateUrl = 'users/deactivate/';
        }
        $.ajax({
            url: stateUrl + id,
            method: 'GET',
            dataType: 'php',
            success: function(){
                console.log(id);
                console.log(role);
    
                // find the row that is the parent of the clicked button - http://api.jquery.com/parent/
                var row = evt.target.parent('tr');
    
                // use the class of the table cell to identify it. http://api.jquery.com/find/
                var statusCell = row.find('.status-column').first();
    
                // now put in the new status. http://api.jquery.com/html/
                if (role == "activate") {
                    statusCell.html('<span class="text-success">Enabled</span>');
                } else {
                    statusCell.html('<span class="text-danger">Disabled</span>');
                }
            }
        });
    });
    

    I’ll leave the button column for you to practice with :).

    Edit: you can also manipulate the DOM with non-jQuery methods that are perhaps more to your liking. This is what jQuery is doing under the hood anyway.

    You can read more about them at MDN.

    // build the new DOM node
    var newStatusCellContent = document.createElement('span');
    newStatusCellContent.setAttribute('class', role == 'activate' ? 'text-enabled' : 'text-danger');
    newStatusCellContent.textContent = role == 'activate' ? 'Enabled' : 'Disabled';
    
    // get the parent <td> node from the jQuery object
    var statusCell = row.find('.status-column').get(0);
    
    // swap the old contents for the new
    var oldChild = statusCell.childNodes[0]
    statusCell.replaceNode(newStatusCellContent, oldChild);
    

    Careful study of the documentation at the above link will probably reveal ways to make that more efficient for your particular case. Keep in mind that this is the same thing the jQuery html() method does — or Angular or any other — and that while it keeps you away from HTML, it doesn’t really improve your code in this case. I really hate HTML, but it’s the tool we’re given.

    Note that php also has DOM libraries; if you wanted, you could use those to build your original page as well, and be done with HTML forever. But I don’t recommend it except in certain cases.

    Login or Signup to reply.
  2. The above answers are adequate – you must use JavaScript given your scenario. It seems the trouble lies in making the leap from dynamic web pages to dynamic HTML.

    Read the last line of the summary here:
    https://en.wikipedia.org/wiki/Dynamic_HTML

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search