CLiveGridView

Motivation:

The data in my database is constantly changing because my database stores device status information such as the up time of a device or the temperature of a device. I need CGridView to refresh continuously. In addition to device status, the database stores device configurations and user settings. The database allows for any number of users to access any number of devices concurrently.

User Guide:

Replace CGridView with CLiveGridView in view files as desired.

Implementation:

I have extended CGridView and called it CLiveGridView. I have created 2 new files to implement CLiveGridView: CLiveGridView.php and jquery.yiilivegridview.js. The update interval is specified in ms (1000 ms = 1 second).

This is the first time I have posted code, comments are requested and welcomed. I am new to web development. Is there are better way to override the yiiGridView.update() function instead of copy, paste, and modify? Only two lines of code were changed in the yiiGridView.update() function; the line that starts with "$filtered=$d.filter…" and the line that follows it.

Deploy:

.../yii/framework/zii/widgets/grid/CLiveGridView.php




<?php

/**

 * CLiveGridView class file based on CGridView class file by Qiang Xue

 *

 */


Yii::import('zii.widgets.grid.CGridView');


/**

 * CLiveGridView continuously refreshes the visible data items in the body of the CGridView table

 *

 **/

class CLiveGridView extends CGridView

{


	public function registerClientScript()

	{

		parent::registerClientScript();

		$id=$this->getId();

		$cs=Yii::app()->getClientScript();


		$cs->registerScriptFile($this->baseScriptUrl.'/jquery.yiilivegridview.js');

		$cs->registerScript(__CLASS__.'# '.$id,"jQuery('# $id').yiiLiveGridView();");

		$cs->registerScript(__CLASS__.'# '.$id.'-live',

		"

			setInterval(function(){;$.fn.yiiLiveGridView.update('status-grid', {});},1000);

		"

		);

	}


}



.../yii/framework/zii/widgets/assets/gridview/jquery.yiilivegridview.js




;(function($) {


	$.fn.yiiLiveGridView = function(options) {

		return $.fn.yiiGridView(options);

	};




	$.fn.yiiLiveGridView.update = function(id, options) {

		var settings = $.fn.yiiGridView.settings[id];

		options = $.extend({

			type: 'GET',

			url: $.fn.yiiGridView.getUrl(id),

			success: function(data,status) {

				$.each(settings.ajaxUpdate, function(i,v) {

					var id='# '+v,

						$d=$(data)

						$filtered=$d.filter(id+' .'+settings.tableClass+' > tbody');

						$(id+' .'+settings.tableClass+' > tbody').replaceWith( $filtered.size() ? $filtered : $d.find(id+' .'+settings.tableClass+' > tbody'));

				});

				if(settings.afterAjaxUpdate != undefined)

					settings.afterAjaxUpdate(id, data);

			},

			error: function(XMLHttpRequest, textStatus, errorThrown) {

				$('# '+id).removeClass(settings.loadingClass);

				alert(XMLHttpRequest.responseText);

			}

		}, options || {});

		if(options.data!=undefined && options.type=='GET') {

			options.url = $.param.querystring(options.url, options.data);

			options.data = {};

		}

		options.url = $.param.querystring(options.url, settings.ajaxVar+'='+id)


		if(settings.beforeAjaxUpdate != undefined)

			settings.beforeAjaxUpdate(id);

		$.ajax(options);

	};

})(jQuery);




This looks like a good idea, I am developing code for a similar situation for one of my projects.

It seems like you could have just made this an extension? Why modify the framework? This will make it more of a pain each time a new version is released.

Take a look at this page from the Definitive Guide: http://www.yiiframework.com/doc/guide/extension.create

DarkNSF is right: This is perfect for an extension. And please don’t use “C” to prefix your classes, it’s reserved for framework classes. So if a user reads some example code, he will know immediately that he has to install the extension first, right by looking at the class name.

Ok. I will create my first extension. Thanks.

Hi uponsun,

have you wrote this extension? I’m wondering where I can find it.

Thank you,

cbi

ps: sorry my english.

Hello there,

I try to write the extension… tested under 1.1.6.r2877. Only made a few cosmetic changes and updated refresh timer to one minute.

Should be installed under protected/extensions and instance like:


$this->widget('ext.widgets.LiveGridView', array( ... ) );

Best,

cbi

I managed to do the same using just this code in the view:




Yii::app()->clientScript->registerScript('autoupdate-activations-application-grid',

		"setInterval(function(){;$.fn.yiiGridView.update('activations-application-grid', {

			data: $(this).serialize()

		});

		return false;},3000);"

);



All you need to reuse it is:

  • update the timer - change 3000 to whatever value you want

  • update the grid id - change from activations-application-grid to whatever your grid is called

Hope this helps

Great extension!

My changes:

  • public property for update interval

  • add ajax events (beforeAjaxUpdate, afterAjaxUpdate, ajaxUpdateError)

  • detect asset path





// working with another paths

$this->widget('application.modules.requests.widgets.LiveGridView', array(

	'id'=>'items-grid',

	'dataProvider'=>$model->with('user')->search(),

	'filter'=>$model,

	'afterAjaxUpdate'=>'checkNewItem()', // support this, running every update

	'updateInterval'=>60000, 

	...

);



Sorry my bad english.

After some search a working solution can be found at

http://www.yiiframework.com/extension/livegridview/