2 rows per item in CGridView

I have a CGridView table which displays basic information about a load of items. Now I need to have an expandable 2nd row per item, so that when the user clicks “view details” at the end of a row, the row beneath opens out and gets populated (via AJAX) with more detailed information about that item. I’ve seen a few other questions around the internet about adding a 2nd row to some items (but not all) in CGridView, but no answers. Does anyone know how to add a 2nd row to every items in CGridView? I guess what I really need to do is make a new widget that extends CGridView and modify the template that it uses to add an empty row (with a unique ID) after each data row, but I can’t find anything in the class reference about how to do this.

I’m going to have a poke around in the CGridView code and see if I can find where the template is set, but would if anyone knows of a solution I’d be very greatful of the time it might save.

This isn’t a GCridView thing rather just plain jquery.

When view details is pressed, you can do something like:




$("#your-grid-id").on("click",".your-view-more-class",function(){

   var $row=$(this).closest("tr");// "this" is an <a/> contained in a <td/> contained in a <tr/>. we need the tr because that's a row, right ?

   var id = $(this).data("id");//assuming your view details link has a data-id="12" attribute.

   $.get("/some-url/here",{id:id},function(data){

     //now your ajax will return the row, based on the id you've sent, so all you have to do is to append it into the grid like:

     $row.after(data.row);

   },"json");

})



You make an excellent point. And inserting the new row when required, rather than populating one of many pre-made empty rows, is undeniably much better. I didn’t know about the closest() method in jquery - very handy indeed! :)

Will let you know when I get it working

How can I set the data-id attribute of each link to have a value which is taken from the data displayed in that row? I tried copying the way that I set values for the ID column:


array(

	'name' => 'ID',

	'value' => '$data->ID',

	'type' => 'text'

)

So in my CButtonColumn I set:


'buttons'=>array(

	'detail'=>array(

		'label' => 'Show Details',

		'options' => array(

			'data-id' => '$data->ID',

			'class' => 'detailsLink'

		)

	)

)

thinking that the data-id would then take the same value as that which appears in my ID column. But instead of getting the ID value for each row, this just sets the data-id to be the string ‘$data->ID’. Taking quotes out obviously causes an error because the $data variable isn’t actually set at this point.

What if you do:




'detail'=> array(

                        'label'=>'Show Details', 

                        'url'  =>'Yii::app()->createUrl("your/controller/action/to/get-row", array("id"=>$data->ID))',

                        'options'=>array('title'=>'Show details','class'=>'detailsLink'),

                    ),  



then in the js function you do :




$("#your-grid-id").on("click",".detailsLink",function(){

   var $row=$(this).closest("tr");

   var url=$(this).attr('href');

   $.get(url,{},function(data){

     $row.after(data.row);

   },"json");

})



would this work for you ?

Thank you!! For the next 10 minutes, you can be my god! :D

Although, for reference, it’s worth noting that I had to stick a ‘return false’ at the end of the jQuery function:


$("#your-grid-id").on("click",".detailsLink",function(){

   var $row=$(this).closest("tr");

   var url=$(this).attr('href');

   $.get(url,{},function(data){

     $row.after(data.row);

   },"html");

   return false;

})

Also, you may notice I changed the jQuery to expect html response, rather than json, because I use a renderPartial to get the contents of my new row. Is there a significant performance hit in sending raw html from the AJAX query, rather than transferring as json and using jquery to translate that into html?

I prefer using json because usually i return an object containing multiple keys, like "result","msg","html" etc.

In your case using html directly is okay, the performance is not a problem, doesn’t matter what option you choose to use(of course html is faster but json is fast too), but when your controller action might return various results then json is the way to go.

Interesting. Thanks for the tip!