Dear nkd
Let us consider an example.
I have a table author : id,name
I have a table book : id,name
I have then a join table book_author : id, b_id, a_id.
An author might have written many books. One book belong to many authors.
In author’s admin page we are going to display authors grid that is followed by books grid.
This is the controller action.
AuthorController.php
public function actionAdmin()
{
$author=new Author('search');
$author->unsetAttributes();
$book=new Book('search');
$book->unsetAttributes();
if(isset($_GET['Author']))
$author->attributes=$_GET['Author'];
if(isset($_GET['Book']))
$book->attributes=$_GET['Book'];
$this->render('admin',array(
'author'=>$author,
'book'=>$book,
));
}
By just copying the code of CGridView widget in admin.php of book views and pasting the code below the
authors grid will render the both the grids with all the functionalities intact.
But the challenge ahead is when user selects a row in authors grid, we have to display the books wriiten by him
in books grid.
To get the author id and utilize it in Book Model, We have to declare a virtual property in Book Model.
We have to utilize the relation between book and book_author.
We have to customize the search method in Book Model.
Book.php
class Book extends CActiveRecord
{
public $authKey;
public function rules()
{
return array(
array('name', 'required'),
array('name', 'length', 'max'=>256),
//Make the authKey safe on search
array('name,authKey,id', 'safe', 'on'=>'search'),
);
}
public function relations()
{
return array(
'bookAuthors' => array(self::HAS_MANY, 'BookAuthor', 'b_id'),
);
}
public function search()
{
$criteria=new CDbCriteria;
$criteria->with=array('bookAuthors');
$criteria->together=true;
$criteria->group='bookAuthors.b_id';
$criteria->compare('t.name',$this->name,true);
$criteria->compare('t.id',$this->id);
//Here catched authKey is utilized for adding condition to criteria.
//We are utilizing the book_author.a_id for filtering books for particular author.
if(isset($this->authKey)&& $this->authKey>0)
$criteria->addCondition("bookAuthors.a_id=$this->authKey");
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
));
}
}
This is what the admin.php in authors view look like.
admin.php
<?php
$this->breadcrumbs=array(
'Authors'=>array('index'),
'Manage',
);
$this->menu=array(
array('label'=>'List Author', 'url'=>array('index')),
array('label'=>'Create Author', 'url'=>array('create')),
);
Yii::app()->clientScript->registerScript('search', "
$('.search-button').click(function(){
$('.search-form').toggle();
return false;
});
$('.search-form form').submit(function(){
$.fn.yiiGridView.update('author-grid', {
data: $(this).serialize()
});
return false;
});
$('#author-grid').on('click.book',$('tr'),function(){
var authKey= $('#author-grid').yiiGridView('getChecked','author-grid_c3');
authKey=authKey[0];
$('#book-grid').yiiGridView('update',{data:{'Book[authKey]':authKey}});
});
");
?>
<h1>Manage Authors</h1>
<p>
You may optionally enter a comparison operator (<b><</b>, <b><=</b>, <b>></b>, <b>>=</b>, <b><></b>
or <b>=</b>) at the beginning of each of your search values to specify how the comparison should be done.
</p>
<?php echo CHtml::link('Advanced Search','#',array('class'=>'search-button')); ?>
<div class="search-form" style="display:none">
<?php $this->renderPartial('_search',array(
'model'=>$author,
)); ?>
</div><!-- search-form -->
<?php $this->widget('zii.widgets.grid.CGridView', array(
'id'=>'author-grid',
'dataProvider'=>$author->search(),
'filter'=>$author,
'columns'=>array(
'id',
'name',
array(
'class'=>'CButtonColumn',
),
array(
'class'=>'CCheckBoxColumn',
),
),
)); ?>
<h2> Get the Books of an Author</h2>
<?php $this->widget('zii.widgets.grid.CGridView', array(
'id'=>'book-grid',
'dataProvider'=>$book->search(),
'filter'=>$book,
'columns'=>array(
array(
'name'=>'authKey',
'htmlOptions'=>array('width'=>'10px'),
),
'id',
'name',
array(
'class'=>'CButtonColumn',
),
),
)); ?>
When we are looking at the admin.php, we have done three important modifications.
-
Obviously we have two grids.
-
We have added a checkBoxColumn to first grid(Author).
-
We have added a bit of javascript.
The purpose of this code is that when user selects a row it parses the
author id and then it sends this id as a get parameter to update the book-grid.
Another important thing is When user clicks the author-grid,
book grid is updated with author id through authKey and when user clicks the book-grid
it is not going to get the value from author id from author grid.It gets updated with its own filters.
This is the code."author-grid_c3" indicates that checkBoxColumn is 4th coumn in the author grid.
$('#author-grid').on('click.book',$('tr'),function(){
var authKey= $('#author-grid').yiiGridView('getChecked','author-grid_c3');
authKey=authKey[0];
$('#book-grid').yiiGridView('update',{data:{'Book[authKey]':authKey}});
});
- We have created a column for authKey in book-grid .The filter cell lively displays the row checked in author-grid. This column is optional.
I hope I helped a bit.
Regards.