How to add additional row in yii cgridview <thead></thead> - yii

I want to add additional row like and , thead-2 has empty cells. These empty cells will be used to 'collspan' in my table.
This is my table now:
https://dl.dropboxusercontent.com/u/10002593/Screenshot%20from%202013-12-31%2008%3A43%3A55.png
And so I would like to achieve the effect:
https://dl.dropboxusercontent.com/u/10002593/output.jpg
Thanks.,

I think the only way to do this is by creating your own CGridView class and overriding the renderTableHeader() method. Create your class like this:
<?php
Yii::import('zii.widgets.grid.CGridView');
class MyGridView extends CGridView {
public function renderTableHeader() {
// Your own table header logic here
}
}
?>
Take a look at the Yii source code to see how the default rendering is done:
https://github.com/yiisoft/yii/blob/1.1.14/framework/zii/widgets/grid/CGridView.php#L495

Related

Set successCssClass and errorCssClass for all input by default

I want set successCssClass and errorCssClass all form's inputs in Yii. How I can doing it.
Unfortunately the the defaults are defined in jquery active form plugin i.e /framework/web/js/jquery.yiiactiveform.js look at the end .
However,as #Michiel suggested, You can extend CActiveForm sth like this:
MyActiveForm extends CActiveForm{
public function error($model,$attribute,$htmlOptions=array(),$enableAjaxValidation=true,$enableClientValidation=true)
{
//my defaults
$defaults=array('errorCssClass'=>'myErrorCss',
'successCssClass'=>'mySuccessCss',
'validatingCssClass'=>'myValidationCss');
$htmlOptions=array_merge($defaults,$htmlOptions);
return parent::error($model,$htmlOptions,$enableAjaxValidation,$enableClientValidation);
}
}
And you have to use your new class e.g
<?php $form = $this->beginWidget('MyActiveForm', array(
..
?>
I don't see a better way right now. Either you have extend jquery.yiiactiveform plugin or CActiveForm .

I've to show menu bar with stats like count of messages and updates, also other counts like gifts and messages count

I want to show a menu bar with stats like count of messages and updates, also other counts like gifts, new friend request and messages count.
This menu will be displayed on the all the pages.
How can I write a single method to get all the stats and render partial into the layout and forget about it?
And in other action just concentrate on the main functionality of the page. Without bothering about the menu.
How can I achieve this in Yii?
You're probably looking for a widget. You could for example extend CMenu and do the queries in init() there:
<?php
Yii::import('zii.widgets.CMenu')
class MainMenu extends CMenu
{
public function init()
{
// Do some count queries here. This is just an example,
// your implementation will differ, of course:
$newMessages = Messages::model()->new()->count();
// Now add the menu items:
$this->items = array(
array(
'label' => "$newMessages New messages",
'url' => array('messages/list'),
),
// ...
);
parent::init();
}
}
You then can use this widget in your views/layouts/main.php:
<?php $this->widget('MainMenu'); ?>
You can use beforeAction to achieve this.
As the docs say "This method is invoked right before an action is to be executed (after all possible filters.) You may override this method to do last-minute preparation for the action."
Also you can define public variables in you main controller (Components/Controller.php) so every other controller has access to these. You can then use them in your layout using $this-variable...
Hope this helps :)
You need to create a class that extends CMenu in /protected/components/extendingclassname
<?php
Yii::import('zii.widgets.CMenu');
class Notifications extends CMenu
{
public function init()
{
//query
$requestor=Yii::app()->user->name;
$count = Requests::model()->count( 'requestor=:requestor', array('requestor' => $requestor));
// Now add the menu items:
$this->items = array(
array(
'label' => "$count New messages",
'url' => array('user/notifications'),
),
// ...
);
parent::init();
}
}
?>
Then include the following line within your /layouts.main.php.Hope this helps a beginner who is not sure where to use the class.That's something Michael Härtl forgot to mention.

How to avoid rendering entire page when using CGridView via AJAX

When creating any ajax request in yii CGridView like (pagination, filtering, ...etc) the result of request will render whole page, how can i avoid that?
I tried to use renderPartial for view but it doesn't work. if this is the solution, how can i do it?
I just need to render the table of GridView not whole page.
Please advice.
In controller:
$this->layout = false;
For me works also $this->renderPartial() in controller instead of $this->render()
if(Yii::app()->request->isAjaxRequest()) $this->renderPartial('view');
else $this->render('view');
U can create class:
class Controller extends CController {
public function beforeAction($action) {
if(Yii::app()->request->isAjaxRequest) $this->layout = false;
return parent::beforeAction($action);
}
}

CListView afterAjaxUpdate event for widget

A widgets can or not be on a controller view, and some of widget affecting listView.
I have stalled on a afterAjaxUpdate JS event in CListView. The widget - is a product filter, which updating the list view. My problem is when I want to update my filters after update list view.
Of course I can configure update code in List View, but I think is wrong, because this behaviors belongs to filter widget.
I tried this in widget
$("#' . $this->listViewId . '").yiiListView.settings.afterAjaxUpdate = function(id, data) {
console.log(id, data);
};
But ListView js going below and obviously it's a bad solution.
I thinking about some public widget events, so I can address to listview widget through filter widget and put event there.
Maybe someone has faced with related problems or have better ideas?
Thanks.
Try this way to add afterAjaxUpdate method for your CListView.
<?php
Yii::app()->clientScript->registerScript('handle_ajax_function', "
function addLoadingClass(id,result)
{
$('.list-view-loading').show();
$('li.previous').addClass('disable');
$('li.next').addClass('disable');
}
function removeLoadingClass(id,result)
{
$('li.previous').removeClass('disable');
$('li.next').removeClass('disable');
try{
$('.list-view-loading').hide();
}catch(e){
alert(e);
}
}
");
?>
<?php
$this->widget('zii.widgets.CListView', array(
'id'=>'handle',
//'ajaxUpdate'=>false,
'dataProvider'=>$data,
'beforeAjaxUpdate'=>'addLoadingClass',
'afterAjaxUpdate'=>'removeLoadingClass',
'itemView'=>'myview',
));
?>

CGridview filter on page load with pre define value in search field

I am working with the Yii framework.
I have set a value in one of my cgridview filter fields using:
Here is my jQuery to assign a value to the searchfield:
$('#gridviewid').find('input[type=text],textarea,select').filter(':visible:first').val('".$_GET['value']."');
And here my PHP for calling the cgridview:
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'bills-grid',
'dataProvider'=>$dataProvider,
'filter'=>$model,
'cssFile'=>Yii::app()->baseUrl . '/css/gridview.css',
'pager'=>array(
'class'=>'AjaxList',
'maxButtonCount'=>25,
'header'=>''
),
'columns' => $dialog->columns(),
'template'=>"<div class=\"tools\">".$dialog->link()." ".CHtml::link($xcel.' Export to excel', array('ExcelAll'))."</div><br />{items}{summary}<div class=\"pager-fix\">{pager}</div>",));
The value appears in the search field and my cgridview works correctly without any issues, but I am unable to trigger the cgridview to refresh or filter. Does anyone know who to trigger the cgridview to filter after page load with a predefined value?
Any help would be greatly appreciated and please let me know if you need additional information.
Thank you.
You can solve the problem without any clientside code modification. In your controller action just set the default value for the attribute as shown below
public function actionAdmin()
{
$model = new Bills();
$model->unsetAttributes();
$model->attribute_name="default filter value";//where attribute_name is the attribute for which you want the default value in the filter search field
if(isset($_GET['Bills'])){
$model->attributes = $_GET['Bills'];
}
$this->render('admin',array('model'=>$model));
}
Have a look at 'default' index action that gii generates:
public function actionIndex()
{
$model = new Bills();
$model->unsetAttributes();
if(isset($_GET['Bills'])){
$model->attributes = $_GET['Bills'];
}
$this->render('index',array('model'=>$model));
}
So if you add one line like: $model->attribute = 'test';, you're done. 'attribute' is of course the attribute that has to have the default filter value (in this case value is 'test') :). So your code looks like:
public function actionIndex()
{
$model = new Bills();
$model->unsetAttributes();
if(isset($_GET['Bills'])){
$model->attributes = $_GET['Bills'];
}
if(!isset($_GET['Bills']['attribute']) {
$model->attribute = 'test';
}
$this->render('index',array('model'=>$model));
}
Of course youre attribute will have a test value (in filter) set up as long as you wont type anything in its filter field. I hope that that's what you're looking for. Your filter should work as always.
Sorry for my bad english :)
Regards
You can use Yii's update:
$.fn.yiiGridView.update('bills-grid', {
type: 'GET',
url: <?php echo Yii::app()->createUrl('controller/action') ?>"?Class[attribute]=<?php echo $_GET['value'] ?>
success: function() {
$.fn.yiiGridView.update('bills-grid');
}
});
This is how i do it, just change the URL, it should be the same controller action of the gridview and change URL parameters to the structure represented in there, should be like Bills[attribute]=value.