• 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Best way to set up AJAX/JQuery process?

#1
Hi,

I'm developing an app which must be AJAX enabled. It's not particularly difficult to set up but as I'm pretty new to AJAX in CI I've had a few concerns about duplication.

Currently, as part of the general CRUD processing on each table, the requirement is a view which lists all records in the table - whenever the user clicks an 'Edit' button for any table entry the app uses Jquery/AJAX to access the db for the appropriate record and display it in a modal form which is part of the same view but hidden until the button is clicked.

when the user has updated the record they clck on a 'Save' button which then uses Jquery/AJAX to access a controller/method to update the record in the db and redisplay the part of the view (the table body) showing all the records in the table, including the updated details. There's also a requirement to do a similarthing when adding records.

Currently, the part of the view which shows the details of each db record is below:

Now, I'm thinking that to redisplay just the table body then I'd need the controller to call a model function which gets all the table records and then processes those records by using an almost exact copy of the foreach code that already exists in the view, passes that back to the controller/method which then echoes it back to the JQuery function which can then target the table body and change the .html

That would me duplicating the view code in the model code which I'm not happy about ... as I say I'm pretty new to AJAX in CI so, there has to be a better way, doesn't there?

Code:
<tbody id="staff-table-body">
<?php
foreach ($data as $staff)
{
$detail_id = $staff['staffid'];
?>
<tr>
<td id="<?php echo $staff['staffid'];?>-s-fname"><?php echo $staff['fname'] ?></td>
<td id="s-lname-<?php echo $staff['staffid'];?>"><?php echo $staff['lname'] ?></td>
<td id="s-dept-<?php echo $staff['staffid'];?>"><?php echo $staff['dept'] ?></td>
<td><input id="<?php echo $staff['staffid'];?>-s-edit" name="btn_add" type="submit" class="s-edit btn btn-sm btn-primary" value="Edit" /></td>
<td>
<?php
echo anchor('staff/edit_staff/'.$staff['staffid'], 'Edit');
?>
</td>
<td>
</tr>
<?php
}
?>
</tbody>
Reply

#2
You could just use a template to build the row in your view and make the template available to your JavaScript by posting it to a hidden input. For example:

PHP Code:
<?php

$rowTemplate 
'
<tr>
    <td id="{staffid}-s-fname">{fname}</td>
    <td id="s-lname-{staffid}">{lname}</td>
    <td id="s-dept-{staffid}">{dept}</td>
    <td><input id="{staffid}-s-edit" name="btn_add" type="submit" class="s-edit btn btn-sm btn-primary" value="Edit" /></td>
    <td><a href="{edit_url}">Edit</a></td>
</tr>'
;
?>
    <tbody id="staff-table-body">
        <?php
        foreach 
($data as $staff)
 
       {
 
           $detail_id $staff['staffid'];
 
           echo str_replace(
 
               array('{staffid}''{fname}''{lname}''{dept}''{edit_url}'),
 
               array($staff['staffid'], $staff['fname'], $staff['lname'], $staff['dept'], site_url("staff/edit_staff/{$staff['staffid']}")),
 
               $rowTemplate
            
);
 
       }
 
       ?>
    </tbody>
</table>
<input type='hidden' id='rowTemplate' value='<?php echo $rowTemplate?>' /> 

Then it's just a matter of performing the same replacement on the value of #rowTemplate via JavaScript. This should be a relatively small amount of code in both languages, and you at still only define the actual HTML once.
Reply

#3
(02-12-2015, 03:14 PM)mwhitney Wrote: You could just use a template to build the row in your view and make the template available to your JavaScript by posting it to a hidden input. For example:





PHP Code:
<?php

$rowTemplate 
'
<tr>
    <td id="{staffid}-s-fname">{fname}</td>
    <td id="s-lname-{staffid}">{lname}</td>
    <td id="s-dept-{staffid}">{dept}</td>
    <td><input id="{staffid}-s-edit" name="btn_add" type="submit" class="s-edit btn btn-sm btn-primary" value="Edit" /></td>
    <td><a href="{edit_url}">Edit</a></td>
</tr>'
;
?>
    <tbody id="staff-table-body">
        <?php
        foreach 
($data as $staff)
 
       {
 
           $detail_id $staff['staffid'];
 
           echo str_replace(
 
               array('{staffid}''{fname}''{lname}''{dept}''{edit_url}'),
 
               array($staff['staffid'], $staff['fname'], $staff['lname'], $staff['dept'], site_url("staff/edit_staff/{$staff['staffid']}")),
 
               $rowTemplate
            
);
 
       }
 
       ?>
    </tbody>
</table>
<input type='hidden' id='rowTemplate' value='<?php echo $rowTemplate?>' /> 

Then it's just a matter of performing the same replacement on the value of #rowTemplate via JavaScript. This should be a relatively small amount of code in both languages, and you at still only define the actual HTML once.

Hi mwhitney,

That's a clever solution, thanks.

I might be able to get away with a
Code:
window.location.reload(true);
in the js but, if not, I'll implement your suggestion.
Reply

#4
The way I prefer to do it is with a table containing an empty "tbody". Then all the rows are build by JS. I have no duplication of code for the rows and the page loads a little faster because it display static html, then after the ajax call has finished the table is filled. In the end it's not faster but I prefer to look at a spinning icon for half a second than look at a blank page for the same amount of time ! Wink
Reply

#5
(02-16-2015, 05:19 PM)includebeer Wrote: The way I prefer to do it is with a table containing an empty "tbody". Then all the rows are build by JS. I have no duplication of code for the rows and the page loads a little faster because it display static html, then after the ajax call has finished the table is filled. In the end it's not faster but I prefer to look at a spinning icon for half a second than look at a blank page for the same amount of time ! Wink

I don't really see the point of loading the page faster just to display a broken table and a spinning icon until the page completes a second request for the data. After all, the data can be sent along with the page, even if you still want to build the table in JavaScript. The only real justification I can see for something like this would be in the case of a long-running query which is triggered by the first request (which then returns the page without the data) and cached until the second request is received. Doing something like that tends to be uncommon in PHP, for various reasons.
Reply

#6
Facing such a problem I would go in a slightly different way. After a record is updated (or added) using a modal dialog I would refresh (using AJAX) the whole table as it is parametrized (page, number of records and pages, filters, sorting). If in the future something changes in the table, it would be easier to be implemented. If the table is long, it is to be shown in pages, so performance is not a sensible problem.

And for making the things easier, for the main table I would use Datatables javascript with server-side processing - it has an API-command for refreshing the whole table content, also it has an automatic way for saving the table state (page, etc.) within browser's memory. Datatables has built-in modal dialog for data entry, but this feature is not for free, as far as I know. But a custom implementation of such a dialog would not be quite difficult.
Reply

#7
(02-17-2015, 09:58 AM)mwhitney Wrote: I don't really see the point of loading the page faster just to display a broken table and a spinning icon until the page completes a second request for the data. After all, the data can be sent along with the page, even if you still want to build the table in JavaScript. The only real justification I can see for something like this would be in the case of a long-running query which is triggered by the first request (which then returns the page without the data) and cached until the second request is received. Doing something like that tends to be uncommon in PHP, for various reasons.

It's not a broken table, it's an empty table. And the faster loading time of the page is just a side effect that I like. It's certainly not the main reason why I do it this way! The main reason is to prevent having PHP and JS code doing the same thing. Coding things in double is the best way to have nasty bugs!
Reply

#8
When doing stuff like this I just create a partial view file of just the HTML tbody table data. The main full CI page loads that, and then when something is updated via ajax it just uses that same view partial to send back in the AJAX request which replaces the current tbody. Yes, I agree that you don't want to code the same thing 2x. So don't!! View partials FTW!! Smile
Reply

#9
(02-17-2015, 04:55 PM)includebeer Wrote: It's not a broken table, it's an empty table. And the faster loading time of the page is just a side effect that I like. It's certainly not the main reason why I do it this way! The main reason is to prevent having PHP and JS code doing the same thing. Coding things in double is the best way to have nasty bugs!

If the purpose of a table is to display data, how is an empty table not broken (except in the very strict sense that the spec allows a table to contain zero or more rows)?

I understand the desire not to duplicate code between PHP and JavaScript. However, as CroNiX mentioned, you can also load the data into a partial view in PHP and send it over, leaving the script to simply insert it into the DOM. Additionally, you could load the same partial view and insert the initial data set on the server side before sending the page without duplicating any code.

The points I'm trying to make are:
- JavaScript should not be required to access your content, and
- triggering a second request on page load is not usually as efficient as it seems.

Even with something as feature-rich as DataTables, I can output an HTML table with all of the functional elements implemented without script (though requiring additional requests as the user interacts with the table), then have the script enhance the table by making all of those features work via AJAX requests or even directly on the client. Or, if you really want to go without implementing any functionality in PHP, you just output the full table and have the script implement all of the features on the client (the non-JS users don't get some of the niceties, but at least they have the data).
Reply

#10
If the table is filled with search results after submitting a form, if it returns no results or you have not submited anything yet, then the table will be empty. How is that a broken table?

Also, if you're going to use ajax, then javascript is required to access your content.

The beauty of programming is that there's not a single solution to a given problem. It's up to you to choose the one you prefer. If you don't want to depend on javascript, then don't use ajax and submit your form the old good old way with full page reload...
Reply


Digg   Delicious   Reddit   Facebook   Twitter   StumbleUpon  


  Theme © 2014 iAndrew  
Powered By MyBB, © 2002-2021 MyBB Group.