This article has moved to this location.
One of the features offered by
sfPropel15Plugin is
sortable behavior. This behavior allows a model to become an ordered list, and provides numerous methods to traverse this list in an efficient way (as said in the doc

). In this article, i would like to share how to implement the sortable behavior, and add the AJAX support to allow direct drag-and-drop ordering.

Sortable table
Schema and Fixtures
Below are schema and fixture used in this article
<?xml version="1.0" encoding="UTF-8"?>
<database name="propel" defaultIdMethod="native" noxsd="true" package="lib.model.TestSortable">
<table name="test_item">
<column name="id" type="INTEGER" required="true" primaryKey="true" autoincrement="true" />
<column name="name" type="VARCHAR" size="255" required="true" />
<behavior name="sortable" />
</table>
</database>
TestItem:
<?php for ($i = 1; $i <= 10; $i++): ?>
test_item_<?php echo $i ?>:
name: Test Item <?php echo $i."\n" ?>
<?php endfor ?>
Make sure you build your model and load the fixture once the data structure is defined by typing in a command line interface:
./symfony propel:build-all-load, then initiate the module by typing :
./symfony propel:generate-admin backend –module=test_sortable TestItem
Non-AJAX sortable table
First we will add two actions, up and down, so that the user can control the order for each item by clicking one of the two actions above.
- Open the generator.yml file, then modify the list section, so it’ll look like below:
list:
display: [ name ]
query_methods: [ orderByRank ]
object_actions:
_edit: ~
_delete: ~
up: { label: Up }
down: {label: Down }
- To enhance the interface, lets change the icon for up and down actions instead of the default one. Add the style below to the main.css:
/*sortable*/
#sf_admin_container ul li.sf_admin_action_up a
{
background: url(/images/arrow_top.gif) no-repeat 0 0;
}
#sf_admin_container ul li.sf_admin_action_down a
{
background: url(/images/arrow_down.gif) no-repeat 0 0;
}
- Initialize the cache directory by visiting the test_sortable module from your browser. Copy _list_td_actions.php file from generated cache directory into test_sortable templates module. Disable the up action for the first item and down action for the last one. Below is the final code.
<td>
<ul class="sf_admin_td_actions">
<?php echo $helper->linkToEdit($TestItem, array( 'params' => array( ), 'class_suffix' => 'edit', 'label' => 'Edit',)) ?>
<?php echo $helper->linkToDelete($TestItem, array( 'params' => array( ), 'confirm' => 'Are you sure?', 'class_suffix' => 'delete', 'label' => 'Delete',)) ?>
<?php if (!$TestItem->isFirst()): ?>
<li class="sf_admin_action_up">
<?php echo link_to(__('Up', array(), 'messages'), 'test_sortable/ListUp?id='.$TestItem->getId(), array()) ?>
</li>
<?php endif; ?>
<?php if (!$TestItem->isLast()): ?>
<li class="sf_admin_action_down">
<?php echo link_to(__('Down', array(), 'messages'), 'test_sortable/ListDown?id='.$TestItem->getId(), array()) ?>
</li>
<?php endif; ?>
</ul>
</td>
- Next we have to define executeListUp() and executeListDown() functions in the actions.class.php
public function executeListUp(sfWebRequest $request)
{
$TestItem = $this->getRoute()->getTestItem();
$TestItem->moveUp();
$this->redirect('@test_item');
}
public function executeListDown(sfWebRequest $request)
{
$TestItem = $this->getRoute()->getTestItem();
$TestItem->moveDown();
$this->redirect('@test_item');
}
The moveUp() and moveDown() functions are built in functions generated by sortable behavior.
The sortable table is now fully functional. Try it by moving items up and down.
Adding AJAX support
Before we begin, let us prepare the required scripts and stylesheets:
- jQuery TableDnD plugin (put into web/js directory).
-
jQuery Ajax Loader plugin.
-
css style for confirmation message (taken from here). You can place this css style in the main.css file.
#confirmationMessage {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 70px;
font: normal 1.4em arial;
line-height: 70px;
text-align: center;
color: #000;
background: #fff;
border-bottom: 1px solid #ddd;
filter:alpha(opacity=92);
-moz-opacity: 0.92;
opacity: 0.92;
display: none;
}
Now that everything is ready, let’s get started.
- Copy _list.php file from generated cache directory into test_sortable templates module, add the code below. If you’ve already loaded jQuery library, remove the first line.
<?php use_javascript('/js/jquery-1.4.4.min.js', 'last') ?>
<?php use_javascript('/js/jquery.ajaxLoader.js', 'last') ?>
<?php use_javascript('/js/jquery.tablednd.js', 'last') ?>
<?php use_stylesheet('/css/jquery.ajaxLoader.css', 'last') ?>
<div id="confirmationMessage"></div>
Define an id for tbody and tr tags, which will be used as parameters for the AJAX request.
<tbody id="table_sortable">
<?php foreach ($pager->getResults() as $i => $TestItem): $odd = fmod(++$i, 2) ? 'odd' : 'even' ?>
<tr class="sf_admin_row <?php echo $odd ?>" id="<?php echo $TestItem->getId() ?>">
<?php include_partial('test_sortable/list_td_batch_actions', array('TestItem' => $TestItem, 'helper' => $helper)) ?>
<?php include_partial('test_sortable/list_td_tabular', array('TestItem' => $TestItem)) ?>
<?php include_partial('test_sortable/list_td_actions', array('TestItem' => $TestItem, 'helper' => $helper)) ?>
</tr>
<?php endforeach; ?>
</tbody>
Add the script to handle the user drag and drop
<script type="text/javascript">
jQuery(document).ready(function() {
jQuery('#table_sortable').tableDnD({
onDrop: function (table, row) {
jQuery.ajax({
type:'POST',
dataType:'json',
data:jQuery.tableDnD.serialize(),
success:function(response){
jQuery('#table_sortable').ajaxLoaderRemove();
jQuery('#confirmationMessage').html(response.message).delay(400)
.slideDown(400).delay(3000).slideUp(400);
},
beforeSend:function(){
jQuery('#table_sortable').ajaxLoader();
},
error : function(request, textStatus, errorThrown) {
jQuery('#table_sortable').ajaxLoaderRemove();
jQuery('#confirmationMessage').html('Oooops!!!.. A problem occurs when ordering items.').delay(400).slideDown(400).delay(3000).slideUp(400);
},
url:"<?php echo url_for('test_sortable/ajaxSortable') ?>"});
return false;
}
});
});
</script>
-
Once the user drags an item and releases it to reorder the table, an AJAX request is made with the following parameters: tableId[]=rowId1&tableId[]=rowId2&tableId[]=rowId3…. Let us add executeAjaxSortable() function to our actions.class.php to serve the AJAX request.
public function executeAjaxSortable(sfWebRequest $request)
{
$this->forward404Unless($request->isXmlHttpRequest());
$items = $request->getParameter('table_sortable');
$data = array();
$data['error'] = false;
$data['message'] = 'The items was ordered successfully.';
//start: create array id ==> order
$newOrders = array();
$i = 1;
foreach ($items as $item) { $newOrders[$item] = $i++; }
//end: create array id ==> order
try
{
TestItemQuery::create()->reorder($newOrders);
}
catch (Exception $e)
{
$data['error'] = true;
$data['message'] = 'A problem occurs when ordering items';
}
sfConfig::set('sf_web_debug', false);
$this->getResponse()->setContentType('application/json');
return $this->renderText(json_encode($data));
}
The reorder function expect the parameter in the format id/position
That’s it!. Refresh your browser, and try to drag and drop a row..
Thanks you
Advertisement
Like this:
Be the first to like this post.
Pingback: How to make simple sortable table using sfPropel15Plugin « Creation site internet Lyon et Paris