I need help with CGridView

Hello all !

I want to build a view where the user can check/uncheck a CCheckBoxColumn in a CGridView, just to indicate whether one contact is in an distribution list (email list) or not. This is a 1-to-Many relationship between the following two tables:

[font="Courier New"]List

[/font][font="Courier New"]-----------------------

List_name varchar(20)

contact_id int(10)


Contact

[/font][font="Courier New"]-----------------------

id int(10)

title varchar(4)

givenname varchar(25)

familyname varchar(25)


[/font]

One contact can be in many distribution lists.

The CGridView is to show all the existent contacts of the selected email list. If it is a new list then the CGridView will show all CCheckBoxColumn unchecked, but if not, then the contacts that belong to that email list must show the CCheckBoxColumn checked.

1787

view.jpg

I need a PHP expression or something to add it to my CGridView widget, in order to check whether for each row in the Contact table is there a corresponding row in the List table.

Such PHP expression would be for the CCheckBoxColumn->check property.




 $this->widget('zii.widgets.grid.CGridView', 

   			array( 

              	'id'=>'contact-grid',

              	'dataProvider'=>$contactModel,

              	'filter'=>$contactModel,

              	'enableSorting'=>true,

              	'summaryText' => '{count} record(s) found.',

              	'selectableRows'=>2,

              	'columns'=>array( 

                            	array(

           						'class'=>'CCheckBoxColumn',

           						'checked'=>'false'   	// The PHP expression would go here !

                            	),

                            	'title', 

                            	'givenname', 

                            	'familyname',

     						)

   			)

    	);




Any tip or idea on how to make this happen?

The relationship is not one-to-many here. It is MANY-To-MANY. Look at this thread for help -

http://www.yiiframework.com/forum/index.php?/topic/16540-cgridview-with-many-to-many/

you need to create a function which will return value to true and false





'checked'=>'contactModel::is_there($data->id)'



Ok, after reading documentation, recommended links, and looking for examples for long hours I finally come to a partial solution:

1797

screenshot.jpg

As shown in the attached image only the contacts in the selected email list will have the checkbox checked.

To this end I only modified the view code as follows:




...

 'columns'=>array(

   array(

  	'class'=>'CCheckBoxColumn',

  	'checked'=>'ContactGroup::model()->findByPk(array(\'contact_id\'=>$data[\'id\'], \'group_name\'=>\'Acknowledgments\')) != Null',

   ),

   'title',

   'givenname',

   'familyname',

)

...



The CCheckBoxColumn->checked property finally has an expression to find out whether are there contacts in the MANY-to-MANY relationship (thanks Mukesh for your advise).

However, I still have two more questions after this approach:

1- [color="#0000FF"]Is there a more efficient method to detect if one record in table "A" is related to another record(s) in table "B" ?[/color]

I think finding every one record in the many-to-many table is not so efficient (as I did here), because I am not taking advantage of the true nature of table relationships. This should be something easier to do.

2- Just to make this work, I hard-coded the second key of the composite key into the parameters for findByPk(). I mean: "group_name"=>"Acknowledgments" which is totally wrong for the functionality that I want to give to this view.

[color="#0000FF"]Is there a way to get the selected value from the generated dropdown list ??[/color] the idea is to write something like "group_name"=>$selectedIndex in that expression instead of having it hard-coded.




echo CHtml::activeDropDownList( $emailModel, 'name',

 		     	CHtml::listData( EmailGroup::model()->findAll(), 'name', 'name'));



Any idea on how to achieve this?

I think,

you need to have an additional field or a new table which contains the information related to both relations

i.e.

products // Table for Products

product_id // PK

categories // Table for Categories

category_id //pk

product_categories(product_id,category_id) // Table Containing Information about relation of a product with category

By this, we can use relations and then object of related row to get the value of other object and hence it can be used in your case.

Ok, I solved my point number 2, but I’m still dealing and wondering how to solve the point number 1.

Yes PeRoChAk, I do have the three tables and their relations specified in their respective model files, but what I don’t know is how to check if one record is in relation with another record(s) in the other table, having a MANY-to-MANY relationship.

What function or expression could I use for the CCheckBoxColumn->checked property to be checked when one record is in relation with another?

Use simple model function

If the key exists in the relation table then it will return true else it will false.

Also, check this one

http://www.yiiframework.com/forum/index.php?/topic/8667-ability-to-pre-populate-checked-value-in-ccheckboxcolumn/

Do you mean I have to call findByPk() or exists() or create my own SQL statement in that function?

Yes, As we have to check it in relation table then exists() should be used.

Ok, since the data source is to populate the CGridView I made the following in my view file:




$contactModel = new CActiveDataProvider('Contact', array(

  'criteria'=>array(

 	'alias'=>'C',

 	'select'=>'C.title, C.givenname, C.familyname, CG.group_name',

 	'join'=>'LEFT JOIN contact_group CG ON C.id = CG.contact_id',

 	'together'=>true

  )

));



And in my CGridView I changed the condition to check/uncheck the CCheckBoxColumn->checked property:




'columns'=>array(

   array(

  	'class'=>'CCheckBoxColumn',

  	'checked'=>'$data[\'group_name\'] == "'.$selectedGroup.'"',

   ),

   'title', 

   'givenname', 

   'familyname',

)



However, the following error is displayed:

Property "Contact.group_name" is not defined.

It is supposed that the conditions are set in the criteria to have a whole query result, but I don’t know how to reference the column that belongs to the related table ( written in the criteria object as CG.group_name ).

What am I missing?

You are missing at


    'checked'=>'$data[\'contact_group.group_name\'] == "'.$selectedGroup.'"',



Thanks PeRoChAk, but the error continued to appear. However, I found the solution to this problem here:

http://www.yiiframew…8811#entry48811

I only had to declare the variable in the respective model:




class Contact extends CActiveRecord {

   

   public $group_name;

   ...

}



That was all. Now everything is working as it should.

When you really need something, it’s either not available, or can’t be found. When you don’t need it, it’s either available, or lays around in plain sight.

- [b]Murphy's law[/b] -

Thanks zaccaria for sharing the tip.

NOTE: moved to proper forum