cgridview related fields filtering - php

I have a problem that I have solved for all but one of the cgridview filters, which is a related field.
I am using a solution Seenivasan has supplied but the related field status does not get added to the string.
here is the cgridview :-
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'tbl-orders-grid',
'dataProvider'=>$dataProvider,
'afterAjaxUpdate'=>"function() {
jQuery('#Orders_date_first').datepicker(jQuery.extend({showMonthAfterYear:false}, jQuery.datepicker.regional['id'], {'showAnim':'fold','dateFormat':'yy-mm-dd','changeMonth':'true','changeYear':'true','constrainInput':'false'}));
jQuery('#Orders_date_last').datepicker(jQuery.extend({showMonthAfterYear:false}, jQuery.datepicker.regional['id'], {'showAnim':'fold','dateFormat':'yy-mm-dd','changeMonth':'true','changeYear':'true','constrainInput':'false'}));
}",
'filter'=>$model,
'columns'=>array(
array(
'name'=>'id',
'type'=>'raw',
'value'=>'str_pad($data->id,8-strlen($data->id),"0",STR_PAD_LEFT)',
'htmlOptions'=>array('style' => 'text-align: right;width: 60px;')
),
array(
'name'=>'date_order_placed',
'filter'=>$dateisOn,
'value'=>'date("d-m-Y",strtotime($data->date_order_placed))',
),
array(
'name'=>'status',
'type'=>'raw',
//'htmlOptions'=>array('id' => 'order_status_search'),
'value'=>'CHtml::value($data,"status.orders_status_name")',
'filter'=>CHtml::listData(OrderStatus::model()->findAll(
array(
'select'=>array('orders_status_name'),
'distinct'=>true
)),"orders_status_name","orders_status_name")//this is the focus of your code
),
array(
'class'=>'EButtonColumnWithClearFilters',
'clearVisible'=>true,
'template'=>'{view}{email}',
'buttons'=>array
(
'email' => array
(
'label'=>'Reprint invoice and email to yourself',
'imageUrl'=>Yii::app()->request->baseUrl.'/images/email.png',
'url'=>'Yii::app()->createUrl("orders/ureprint", array("id"=>$data->id))',
),
),
),
),
)); ?>
here is the php and js that adds the current filter values to the url.
echo CHtml::button('List Orders',array('id'=>'listelement'));
Yii::app()->clientScript->registerSCript('test','
$("body").on("click","#listelement",function(){
var str="&";
$.each($("#tbl-orders-grid input").serializeArray(),function(i,j){
str=str+j.name+"="+j.value+"&";
});
window.location="'.CHtml::normalizeUrl(array('orders/index')).'"+str;
});
');
The other filters, dates and id, work perfectly. They are added to the url above. Status is not.

1- you need to define new filters in your model serach() methode for example like
$criteria->compare('Restaurant.Name',$this->Name,true);
Restaurant is your relation key , name : value from another table related to this fk
2- you have to add value of gridview column like :
view:
array(
'name' => 'Restaurant.Name',
'header' => 'Username',
'filter' => CHtml::activeTextField($model, 'name'),
'value' => '$data->Restaurant->Name',
This link will help you
yii CGridView filter with relations

Related

yii filter in two cgrdiview with same model

I have two cgridview that using same model.
When I use filters, the textfield names are the same (model class).
It's possible modify this name?
example:
$model1 = new ClassName;
$model2 = new ClassName;
if(isset($_GET['cgrdiview_1'])) {
$model1->attributes = $_GET['cgrdiview_1'];
}
if(isset($_GET['cgrdiview_2'])) {
$model2->attributes = $_GET['cgrdiview_2'];
}
Instead I have:
$_GET['model_class']
for both cgridview
Yes, It is possible by adding an id field.
The id attribute specifies a unique id for an HTML element (the value must be unique within the HTML document).
The id attribute is most used to point to a style in a style sheet, and by JavaScript (via the HTML DOM) to manipulate the element with the specific id.
If you check the Yii API Documentation for CGridView You can see that you can set an id field for the CGridview.
In your view, change the CGridview code to contain the following:
'id' => 'cgridview_1'
This code needs to be added at the top of your gridview. For example:
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'cgridview_1',
'dataProvider'=>$dataProvider,
'columns'=>array(
'title', // display the 'title' attribute
'category.name', // display the 'name' attribute of the 'category' relation
'content:html', // display the 'content' attribute as purified HTML
array( // display 'create_time' using an expression
'name'=>'create_time',
'value'=>'date("M j, Y", $data->create_time)',
),
array( // display 'author.username' using an expression
'name'=>'authorName',
'value'=>'$data->author->username',
),
array( // display a column with "view", "update" and "delete" buttons
'class'=>'CButtonColumn',
),
),
));
I solved my problem with custom filter in each column:
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'cgridview_2',
'dataProvider' => $data,
'filter' => $filter,
'columns'=>array(
array(
'name' => 'column1',
'filter' => CHtml::textField("cgridview2[column1]", $filter->column1),
),
array(
'name' => 'column2',
'filter' => CHtml::textField("cgridview2[column2]", $object->column2),
),

Accessing value of indirectly related models

I am displaying a CGridView below CDetailView on view.php page for Company model. I have problem in displaying values in CGridView using company details. The company model has an array of CompanyAddresses which is used as CArrayDataProvider for CGridView.
$config = array();
$dataProvider = new CArrayDataProvider($rawData=$model->companyAddresses,$config);
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider'=>$dataProvider
, 'columns'=>array(
//'id',
array('header'=>'SN.',
//'value'=>'++$row', // may nt work with pagination but the below does work
'value'=>'$this->grid->dataProvider->pagination->currentPage * $this->grid->dataProvider->pagination->pageSize + ($row+1)',
),
'address',
array(
'name'=>'Tehsil',
//'value'=> Utility::getTehsilName(Tehsil::model()->findByPk('tehsil_id')),
'value'=> Utility::getTehsilName($this->loadModel('tehsil_id')),
//'value'=> Tehsil::model()->findByAttributes( array('id' => 'tehsil_id' ) )->name,
),
array(
'name'=>'address_tag_id',
'value'=>AddressTag::model()->findByPk('address_tag_id'),
),
)
));
I am not able to fetch Tehsil_Name from Tehsil Table which has its ID inside CompanyAddress table.
Your using value attribute is wrong, check this:
'value'=>function($data){
return Utility::getTehsilName($data->tehsil_id);
},
value is a php expression that is evaluated to produce the contents of the gridview cell as below
'value' => 'Utility::getTehsilName($this->grid->controller->loadModel($data->tehsil_id))'
If you had used relation chaining to solve this your expression would have been simplified to say:
'value' => '$data->model1->tehsil->name'
where model1 is the middle relation.

Create Custom Row in yii Cgridview

I had created a yii Cgridview but how to make custom row in the it. I want to make the custom row whose data is static not related to database?
the problem is similar to below
http://www.yiiframework.com/forum/index.php/topic/47751-insert-first-row-in-cgridview/
insert static first row in cgridview yii
Check this grid row
array(
'name'=>'some_name',
'value'=>'$data->getCountryNameOrStaticStringOrWhatever()',
),
In model
public function getCountryNameOrStaticStringOrWhatever(){
return 'my static content or whatever';
}
you can do it with javascript and jQuery:
add 'afterAjaxUpdate' => 'addStaticRaw', to CGrid config
and register js script:
function addStaticRaw(){
$('#party-ledger-grid tbody tr:first').before("<tr><td>Your static raw blah blah</td></tr>");
}
I was looking for a similar solution and came across this:
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'something',
'dataProvider'=>$provider,
'columns'=>array(
array(
'name' => 'name',
'header' => 'Name',
'footer' => 'name column for extra row',
),
array(
'name' => 'email',
'header' => 'e-Mail',
'footer' => 'email column for extra row'
),
)
)
Simply fill out the footer elements of each column with the data from you extra row.
It works like a charm!

pageSize bug in yii grid when using joins

I have this search using joins. The results are correct but yii grid does not show all of the results even if the pagesize selected is greater than number of result.
here's my code :
if($_GET['BaseIar']['description'] !='empty'){
$criteria->with = array('class','classSi',);
$this->description=$_GET['BaseIar']['description'];
$criteria->compare('class.description', $this->description, true);
$criteria->compare('classSi.description', $this->description, true, 'OR');
}
here are the relations:
public function relations() {
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'class' => array(self::HAS_ONE, 'BaseEiEquipItem', 'iar_no'),
'classSi' => array(self::HAS_ONE, 'BaseSiReceivedItem','iar_no'),
);
}
here's the grid:
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'base-iar-grid',
'dataProvider'=>$searchModel->search(),
'columns'=>array(
array(
'class'=>'CCheckBoxColumn',
'id'=>'base-iar-id',
'selectableRows'=>2, // multiple rows can be selected
),
'iar_id',
'dateInspected',
array(
'name'=>'inspectedBy',
'value'=>'(!empty($data->inspectedBy))?$data->inspectedBy0->person->lastName.", ".$data->inspectedBy0->person->firstName." ".$data->inspectedBy0->person->middleName:"---"',
),
array(
'name'=>'endUser',
'value'=>'(!empty($data->endUser))?$data->endUser0->person->lastName.", ".$data->endUser0->person->firstName." ".$data->endUser0->person->middleName:"---"',
),
'dateReceived',
array(
'name'=>'receivedBy',
'value'=>'(!empty($data->receivedBy))?$data->receivedBy0->person->lastName.", ".$data->receivedBy0->person->firstName." ".$data->receivedBy0->person->middleName:"---"',
),
array(
'name'=>'requisitionOffice',
'value'=>'(!empty($data->requisitionOffice))?$data->requisitionOffice0->code:"---"',
'value'=>'$data->requisitionOffice0->code'
),
'prNo',
'poNo',
array(
'class'=>'InfosysButtonColumn',
'template'=>'{view}',
'afterDelete'=>'function(link,success,data){
if(success){
jSuccess("Delete completed successfully!");
}
}',
'buttons'=>array(
'view' => array(
'label' => 'View details',
'url' => 'Yii::app()->createUrl("pims/IAR/BaseIar/view", array("id"=>$data["id"]))'
),
),
'header'=>CHtml::activeDropDownList($model,'pageSize',array('10'=>'10','20'=>'20','30'=>'30','50'=>'50','100'=>'100','ALL'=>'All'),array('onchange'=>'$.fn.yiiGridView.update("base-iar-grid", {data:{pageSize:$(this).val()}});')),
),
)
));
What might be the correct way to declare multiple relations in $criteria->with?
Hey I found this piece of example code in the docs for with(), maybe it'll help you:
Post::model()->with(array(
'author'=>array('select'=>'id, name'),
'comments'=>array('condition'=>'approved=1', 'order'=>'create_time'),
))->findAll();

Retain Checkbox values in Yii gridview pagination

I have a gridview which contains a checkbox column and also uses pagination. When I check some checkboxes in the first page and navigate to the second page and check another one in the second page, the options I checked in the first page is not retained there. Is it posssible to retain the checkbox values during pagination?
Code for Gridview is
$widget = $this->widget('zii.widgets.grid.CGridView', array(
'dataProvider' => $model->search(),
'cssFile' => Yii::app()->baseUrl . '/media/js/admin/css/admingridview.css',
//'filter' => $model,
'ajaxUpdate' => true,
'enablePagination' => true,
'columns' => array(
array(
'name' => 'id',
'header' => '#',
'value' => '$this->grid->dataProvider->pagination->currentPage * $this->grid->dataProvider->pagination->pageSize + ($row+1)',
),
array(
'class' => 'CCheckBoxColumn',
'selectableRows' => '2',
'header' => 'Selected',
),
array(
'name' => 'fb_user_id',
'header' => 'FaceBook Id',
'value' => 'CHtml::encode($data->fb_user_id)',
),
array(
'name' => 'first_name',
'header' => 'Name',
'value' => 'CHtml::encode($data->first_name)',
),
array(
'name' => 'email_id',
'header' => 'Email',
'value' => 'CHtml::encode($data->email_id)',
),
array(
'name' => 'demo',
'type' => 'raw',
'header' => "Select",
'value' => 'CHtml::checkBox("email[]","",array("class"=>"check","value"=>$data->email_id))',
),
),
));
Edit:
Extension for remembering the selected options in gridview,check this link Selgridview
Thanks to bool.dev
You could use sessions/cookies to store the checked values. I'm not very sure how to make cookies work, so i'll tell you how to do it with sessions. Specifically the user session that yii creates.
Now to use sessions we need to pass the checked (and unchecked) ids to the controller, therefore we'll modify the data being sent to the controller on every ajax update(i.e between paginations), to do this we exploit the beforeAjaxUpdate option of CGridView.
I'm also using CCheckBoxColumn instead of the following in your code(of course you can modify the solution to suit your own needs):
array(
'name' => 'demo',
'type'=>'raw',
'header' => "Select",
'value' => 'CHtml::checkBox("email[]","",array("class"=>"check","value"=>$data->email_id))',
),
GridView Changes:
<?php $this->widget('zii.widgets.grid.CGridView', array(
// added id of grid-view for use with $.fn.yiiGridView.getChecked(containerID,columnID)
'id'=>'first-grid',
'dataProvider'=>$model->search(),
'cssFile' => Yii::app()->baseUrl . '/media/js/admin/css/admingridview.css',
// added this piece of code
'beforeAjaxUpdate'=>'function(id,options){options.data={checkedIds:$.fn.yiiGridView.getChecked("first-grid","someChecks").toString(),
uncheckedIds:getUncheckeds()};
return true;}',
'ajaxUpdate'=>true,
'enablePagination' => true,
'columns' => array(
array(
'name' => 'id',
'header' => '#',
'value' => '$this->grid->dataProvider->pagination->currentPage * $this->grid->dataProvider->pagination->pageSize + ($row+1)',
),
array(
'name' => 'fb_user_id',
'header' => 'FaceBook Id',
'value' => 'CHtml::encode($data->fb_user_id)',
),
array(
'name' => 'first_name',
'header' => 'Name',
'value' => 'CHtml::encode($data->first_name)',
),
array(
'name' => 'email_id',
'header' => 'Email',
'value' => 'CHtml::encode($data->email_id)',
),
/* replaced the following with CCheckBoxColumn
array(
'name' => 'demo',
'type'=>'raw',
'header' => "Select",
'value' =>'CHtml::checkBox("email[]","",array("class"=>"check","value"=>$data->email_id))',
),
*/
array(
'class' => 'CCheckBoxColumn',
'selectableRows' => '2',
'header'=>'Selected',
'id'=>'someChecks', // need this id for use with $.fn.yiiGridView.getChecked(containerID,columnID)
'checked'=>'Yii::app()->user->getState($data->email_id)', // we are using the user session variable to store the checked row values, also considering here that email_ids are unique for your app, it would be best to use any field that is unique in the table
),
),
));
?>
Pay special attention to the code for beforeAjaxUpdate and CCheckBoxColumn, in beforeAjaxUpdate we are passing checkedIds as a csv string of all the ids(in this case email_ids) that have been checked and uncheckedIds as a csv string of all the unchecked ids, we get the unchecked boxes by calling a function getUncheckeds(), which follows shortly. Please take note here, that when i was testing i had used an integer id field (of my table) as the unique field, and not an email field.
The getUncheckeds() function can be registered like this anywhere in the view file for gridview:
Yii::app()->clientScript->registerScript('getUnchecked', "
function getUncheckeds(){
var unch = [];
/*corrected typo: $('[name^=someChec]') => $('[name^=someChecks]') */
$('[name^=someChecks]').not(':checked,[name$=all]').each(function(){unch.push($(this).val());});
return unch.toString();
}
"
);
In the above function pay attention to the selectors and each and push function.
With that done, we need to modify the controller/action for this view.
public function actionShowGrid(){
// some code already existing
// additional code follows
if(isset($_GET['checkedIds'])){
$chkArray=explode(",", $_GET['checkedIds']);
foreach ($chkArray as $arow){
Yii::app()->user->setState($arow,1);
}
}
if(isset($_GET['uncheckedIds'])){
$unchkArray=explode(",", $_GET['uncheckedIds']);
foreach ($unchkArray as $arownon){
Yii::app()->user->setState($arownon,0);
}
}
// rest of the code namely render()
}
That's it, it should work now.
For developing that scheme you would need to know working of what happens when you navigate.
When ever you navigate to a pagination page ajax calls are made and new data is received and it is fetched from CActive Record or what ever the data source. New data is in accordance of database records or source records. when you come back to previous page again Ajax call is made and content is updated so same comes as it is in database.
what i feel is you should save data of checked items temporary and make it permanent if action is made.
You can do something like this
<script type="text/javascript">
$("input:checkbox").click(function () {
var thisCheck = $(this);
if (thisCheck.is (':checked')){
// do what you want here, the way to access the text is using the
// $(this) selector. The following code would output pop up message with
// the selected checkbox text
$(this).val());
}
});
</script>
you can save temporary storage somewhere
Also make this work on normal form submit:
I wanted to add this as a comment on bool.dev's answer, but I do not have enough reputation to do that yet. So I had to put it in a separate answer.
bool.dev, your answer is great and it works well, thanx.
However, as intended, it only works when ajax calls update the gridview. I have the gridview forming part of a form, so I wanted it to also work on normal submission of the form, otherwise the checkboxes are not loaded again when there are other validation errors on the form.
So, in ADDITION to what you did, I added hidden fields on my form e.g.:
<input type="hidden" name='checkedBox1' id='checkedBox1' value=''>
<input type="hidden" name='uncheckedBox1' id='uncheckedBox1' value=''>
Then, before submitting the form, my sumbit button runs your getChecked() and getUncheckeds() functions and store their results in the hidden fields:
if ($('#checkedBox1').length >0) {$('[name=checkedBox1]').val(getChecked());}
if ($('#uncheckedBox1').length >0) {$('[name=uncheckedBox1]').val(getUncheckeds());}
In the controller, besides from checking for $_GET['checkedIds'], you also check for $_POST['checkedBox1'] and store its values to session in the same way you do for $_GET['checkedIds'], using the same session variable.
Do the same with $_POST['uncheckedBox1'].
That should work.

Categories