Hi there, All,
I would like to ask for some help with the following issue:
On the main page of my app I have a CGridView widget updated every 5 seconds. For this purpose I use CController::renderPartial(). Here are some code snippets (for first, please look over the code within /* */ code blocks):
views/site/index.php:
<div id="active_device_grid">
<?php
$this->renderPartial('activeDeviceGrid', array('model'=>$model, 'dataProvider'=>$dataProvider));
?>
</div>
<script type="text/javascript">
// On page load start periodically calling refresh
$(function () {
/**********
orderBy = '';
order = ''; // 'asc' or 'desc'
***********/
// Start refreshing the active device list
refresh();
});
function refresh() {
$.ajax({
//type: 'POST',
url: "<?php echo CController::createUrl('site/indexUpdate');?>",
dataType: 'html',
success:function(reply)
{
$('div#active_device_grid').html(reply);
// Bind event handler to the just loaded html elements
/**********
$("table.items th a").click(function() {
clickHandler(this);
});
**********/
}
});
setTimeout(refresh, 5000);
console.log("refresh called");
}
/********************
function clickHandler(element) {
console.log('click event');
// Little rude but ok.
columnName = $(element)[0].innerText; // e.g. Device name
columnName = columnName.replace(' ','_'); // e.g. Device_name
columnName = columnName.toLowerCase(); // e.g. device_name
if(orderBy != columnName)
{
orderBy = columnName;
order = 'asc';
}
else if(order == 'asc')
{
order = 'desc';
}
else
{
order = 'asc';
}
}
********************/
</script>
views/site/activeDeviceGrid.php:
<?php
$dataProvider = $model->searchActives();
$dataProvider -> setPagination( array( 'pageSize' => 20, ) );
/**********
$dataProvider -> setSort( array(
'defaultOrder'=>"$order_by $order",
));
**********/
$this->widget('zii.widgets.grid.CGridView', array(
'id' =>'active-device-grid',
'dataProvider' =>$dataProvider,
'filter' =>$model,
'columns'=>array(
'device_id',
'device_name',
'device_type',
'device_firmware_version',
array(
'name' => 'equipment_name',
/**********
'sortable' => true,
**********/
'value' => array($model, 'getEquipmentNameFromDb'),
),
),
));
?>
controllers/SiteController.php:
public function actionIndexUpdate()
{
$model=new Device('search');
$model->unsetAttributes(); // clear any default values
if(isset($_GET['Device']))
{
$model->attributes=$_GET['Device'];
}
/**********
$order_by = $_GET['orderBy'];
$order = $_GET['order'];
**********/
$grid = $this->renderPartial(
'activeDeviceGrid', array(
'model'=>$model,
/**********
'orderBy'=>$order_by,
'order'=>$order,
**********/
),
true
);
echo $grid;
}
models/Device.php:
public function getEquipmentNameFromDb($data)
{
// Get connected equipment from DB through equipment's id
$eq_id = $data->equipment_id;
$query = "SELECT equipment_name FROM equipment WHERE equipment_id=$eq_id";
$eq_name = Yii::app()->db->createCommand($query)->queryScalar();
if( $eq_name )
{
return $eq_name;
}
else // No equipment connected to device
{
return '';
}
}
public function searchActives()
{
$criteria=new CDbCriteria;
$criteria->compare('device_id',$this->device_id,true);
$criteria->compare('device_name',$this->device_name,true);
$criteria->compare('device_type',$this->device_type,true);
$criteria->compare('device_active', 1); // !!!
$criteria->compare('device_firmware_version',$this->device_firmware_version,true);
$criteria->compare('device_available_storage',$this->device_available_storage,true);
$criteria->compare('equipment_id',$this->equipment_id,true);
$criteria->compare('device_created',$this->device_created,true);
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
'sort'=>array(
'defaultOrder'=>'device_id ASC',
),
));
}
So an external application keeps the database up to date managing active/inactive devices (with device_active set to 1 or 0 in the data table.
It works fine, with two annoying little problems.
-
First, if I sort the grid data by any of the columns, the renderPartial() method called by the refresh() javascript function, of course, resets the sorting.
-
Second, I cannot make the grid be sortable by the calculated column ‘equipment_name’.
However I made some efforts as you can see taking a look on lines within the code block. That would be, in the main view in the javascript part, keep tracking the user interaction with the grid and having the actual state in two variables orderBy (column name) and order (ascending or descending), and pass it towards the partially rendered view (activeDeviceGrid.php). With this I have got two other problems
The view activeDeviceGrid.php said "Undefined variable: order_by", what can be in connection with this article: link, but I cannot figure out the solution.
Secondly the click event handler in index.php gets invoked only once after each refresh() call.
For now I’ve got a bit confused about all this , but I hope this post is clear enough.
I would be very thankful for an answer of any issue around this subject or another cleaner way to do all that I want.
Best regards,
Klorti