Dear Friend
At the outset, I want to stress that in this thread people have used checkbox list to choose data from the related table.That means that they are deaing with minimal set of records.
In the following implementation, I used gridview to pick the records. I also disabled pagination.
With pagination, I am finding difficult to get the things done.That means that it is useful in situations where
we have minimal set of relational records.
The scenario:
I have three models representing many_many relation.
1.Meeting(table:meeting fields:id,name)
2.Member(table:member fields:id,name,age,sex,qulification)
3.MeetingMember(table:meeting_member fields:id,meeting_id,member_id).
Each meeting is attended by many members. We are taking the attendance and storing it in join table(meeting_member).
MeetingController.php
public function actionCreate()
{
$model=new Meeting;
$member=new Member('search');
$member->unsetAttributes();
if(isset($_GET['Member']))
$member->attributes=$_GET['Member'];
if(isset($_POST['Meeting']))
{
$model->attributes=$_POST['Meeting'];
if($model->save())
{
if(isset($_POST['member']) && $_POST['member']!=="" )
{ $members=explode(",",$_POST['member']);
foreach($members as $member)
{
$meme=new MeetingMember;
$meme->meeting_id=$model->id;
$meme->member_id=$member;
$meme->save(false);
}
}
$this->redirect(array('view','id'=>$model->id));
}
}
$this->render('create',array(
'model'=>$model,
'member'=>$member,
));
}
public function actionUpdate($id)
{
$model=$this->loadModel($id);
$member=new Member('search');
$member->unsetAttributes();
if(isset($_GET['Member']))
$member->attributes=$_GET['Member'];
if(isset($_POST['Meeting']))
{
$model->attributes=$_POST['Meeting'];
if($model->save())
{ if(isset($_POST['member']) && $_POST['member']!=="" )
{ $members=explode(",",$_POST['member']);
MeetingMember::model()->deleteAll("meeting_id=:mid",array(":mid"=>$model->id));
foreach($members as $member)
{
$meme=new MeetingMember;
$meme->meeting_id=$model->id;
$meme->member_id=$member;
$meme->save(false);
}
}
$this->redirect(array('view','id'=>$model->id));
}
}
$this->render('update',array(
'model'=>$model,
'member'=>$member,
));
}
in both create.php and update.php the following modifications done.
php echo $this->renderPartial('_form', array('model'=>$model,'member'=>$member));//$model and $member is carried to the view.
In the view we are placing the grid inside the form,the grid has checkbox column.when user checks the rows,
primary key values of member records are placed as a string inside a text field. For that we have registered a script.When we are submitting the form, string of ids is converted to array in controller.
views/meeting/_form.php
<div class="form">
<?php $form=$this->beginWidget('CActiveForm', array(
'id'=>'meeting-form',
'enableAjaxValidation'=>false,
)); ?>
<p class="note">Fields with <span class="required">*</span> are required.</p>
<?php echo $form->errorSummary($model); ?>
<div class="row">
<?php echo $form->labelEx($model,'name'); ?>
<?php echo $form->textField($model,'name',array('size'=>60,'maxlength'=>64)); ?>
<?php echo $form->error($model,'name'); ?>
</div>
<?php $this->widget('zii.widgets.grid.CGridView', array(
'id'=>'member-grid',
'dataProvider'=>$member->search(),
'filter'=>$member,
'enablePagination'=>false,
'columns'=>array(
'id',
'name',
'age',
'email',
'qualification',
array(
'class'=>'CCheckBoxColumn',
'selectableRows'=>2, //enabling multiselect option
'checked'=>function($data,$row)use($model){return in_array($data->id,$model->participants);},
),//this ensures that during update corresponding records get checked.
array(
'class'=>'CButtonColumn',
),
),
)); ?>
<!--placing a textfield to collect the ids from member-grid-->
<?php echo CHtml::encode('members');echo "</br>";?>
<?php echo CHtml::textField('member','',array('id'=>'member'));?>
<div class="row buttons">
<?php echo CHtml::submitButton($model->isNewRecord ? 'Create' : 'Save'); ?>
</div>
<?php $this->endWidget(); ?>
</div><!-- form -->
<?php
Yii::app()->clientScript->registerScript('collectMember','
$("#member").val('.CJavaScript::encode($model->participants).');
$("body").on("change","input[type=\"checkbox\"]",function(){
var value=$("#member-grid").yiiGridView("getChecked","member-grid_c5");
$("#member").val(value);
});
');
/**
*member-grid_c5 indicates that the checkBoxColumn is in the sixth column of the grid.
*/
The following things in the model, ensures that during the update the virtual property participant gets filled up.It helps in updating the checkboxes in the member grid.
Model(Meeting.php)
public $participants=array();
public function afterfind()
{
$this->participants=Yii::app()->db->createCommand()
->select("member_id")
->from("meeting_member")
->where("meeting_id=".$this->id)
->queryColumn();
return parent::afterFind();
}
Model(Member.php)
public function search()
{
$criteria=new CDbCriteria;
$criteria->compare('id',$this->id);
$criteria->compare('name',$this->name,true);
$criteria->compare('age',$this->age);
$criteria->compare('email',$this->email,true);
$criteria->compare('qualification',$this->qualification,true);
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
'pagination'=>false,// disabled the pagination.
));
}
I hope this would help you a bit.
The problem is here is that by disabling pagination we can not deal with large set of data.
Regards.