Reacting on click anywhere in CGridView's row

Hi there,

I need to build CGridView that will do exactly the same as now happens, when user clicks currently on View in CButtonColumn, no matter where within row user clicks.

Is there any other way to do it except changing each CDataColumn to CLinkColumn? Cause this way I can only reacts on clicking on links / values / cell contents and ideal situation for me would be to catch HTML’s td onClick and make it work just as clicking on View now works.

I usually use CListView for this kind of pourpouse.

With a bit of effort you can style CListView to look like a grid view, and then you have complete control on all html.

Here you go




'selectableRows'=>1,

'selectionChanged'=>'function(id){ location.href = "'.$this->createUrl('view').'/id/"+$.fn.yiiGridView.getSelection(id);}',



/Tommy

I’m also looking for this,thanks Tri for sharing. It works like a charm :)

All that’s left to do is to change my CSS to change my mouse cursor to pointer. Great :)

Let me just remind for others, that in current implementation of Yii you can’t set htmlOptions per each table row and currently the only option to achieve, what you want to do is to use CSS file and add into it line:


.grid-view table.items tr td {cursor: pointer}

I found this solution in other disscussion and pasting it here, so others wouldn’t have to search for it.

@Tommy: Thanks for another brilliant solution! :]

What I did was simply change the class of my gridview:




...

'htmlOptions'=>array(

		'class'=>'grid-view mgrid_table',

	),

...



and in my css:




.mgrid_table tbody:hover

{

	cursor: pointer;


}



I added a particular class to this table so that it won’t affect tables in ‘admin’ view which uses grid-view as well. And in my css, I only wanted the <tbody> to have the pointer cursor. Giving the header the pointer cursor might give the user the idea that the table can be sorted by clicking any part of the header, and might disappoint them that it’s not.

@tri: Arrrgh! :expressionless:

Your solution is using CGridView’s internal jQuery function for obtaining ID of clicked row. After slight changes to your code I’m getting addresses I need in one of my modules, for example:


http://localhost/app_name/zlecenia/view.html?id=5453

But, is there any way I can build address that would contain not ID, but a value of cell of particular column in selected row? For example:


http://localhost/app_name/zlecenia/index.html?Zlecenia[PESEL]=79011714729

Where value of first and only parameter (79011714729 in this example) is taken from particular cell in clicked row. This feature I need in another module of my application.

I’ve tried solution mdomba once gave me for generating in CGridView’s CButtonColumn delete button click a delete confirmation including some value from some of cell in the row, where user clicked on delete button, i.e.:


'selectionChanged'=>'function(id){alert($(this).parent().parent().children(":nth-child(1)").text());}',

But either I’m missing something or this does not works here (however works brilliantly in deleteConfirmation - tested and confirmed). It returns empty string, not current cell value (however trimming .text() off displays “[object] [object[” alert message, therefore object exists I only can’t access its properties somehow).

But, your solution requires to either add this class to any CGridView, where you want to have hand-cursor, while my solution (slightly updated after you - remaining on original class name):


.grid-view tbody:hover {cursor: pointer}

Will add you hand-cursor to every CGridView, as every CGridView is build by default upon .grid-view class.

But maybe this was you intention to add hand-cursor only to a specific one CGridView, then your solution is very good.

@Trejder,

Right, I want to control the tables which will only have this feature. I particularly does not want the ‘admin’ view file to be viewable with the click of the row, since they also use ‘grid-view’ class. :)

@Trejder… note that my solution was specific to the button column… if you want to use it in another column you need to remove one parent() call… or better said… you need to calculate how many parents() you need to go up to get to the row object…

Check again the explanation I gave in this post - http://www.yiiframework.com/forum/index.php?/topic/13804-dynamic-deleteconfirmation-in-the-cbuttoncolumn/page__view__findpost__p__68427

Yes, you’re right I missed that it this situation I’m clicking in the column, not on the button. Therefore - as you mentioned - I need to remove one .parent(). Which actually doesn’t explain why code produced this way:


'selectionChanged'=>'function(id){alert($(this).parent().children(":nth-child(1)").text());}'

doesn’t work - i.e. again an empty string is returned.

Edit: I’ve even tried the simpliest as it can be:


'selectionChanged'=>'function(id){alert($(this).text())}'

to display contents of clicked cell. But this results in no alert and "elems is undefined in /assets/739c509d/jquery.js, line 3422" error drops into JS console after clicking anything in CGridView.

Problem is that "this" is not the column object or row when used like this…

A similar problem was here - http://www.yiiframework.com/forum/index.php?/topic/13804-dynamic-deleteconfirmation-in-the-cbuttoncolumn/page__view__findpost__p__72358

So best way to solve this is to write a custom javascript

Something like




Yii::app()->clientScript->registerScript('dc', "

$('#company-grid table tbody tr').click(function()

{

    	alert($(this).children(':nth-child(1)').text());

});

");



where "company-grid" is the ID of the CGridView

For the very same purpose you can also use id of CGridView, which is declared most of the time (and as every ID, always points only to current, the only one), as it is used in gridview’s update JavaScript code. There is no need to add additional class name for distinguishing grid view.

But you probably knows this! :]

Thanks (+1)! Works like a charm. As every of your solutions! :]

Hi,

I use your method, and like it, but noticed, that it works only in first page, but when I click on any other page, redirection is not working. When I return to page it worked for the first time, then it also fails. Maybe there are some jquery conflicts, because CGridView is using jquery pagination?




<?php Yii::app()->clientScript->registerScript('gridclick', "

$('#products-grid table tbody tr').click(function()

{

        location.href = '".$this->createUrl('/produktas')."/'+$(this).children(':nth-child(1)').text();

});

");

?>

<?php $this->widget('zii.widgets.grid.CGridView', array(

        'id'=>'products-grid',

        'dataProvider'=>$product->search(),

        'filter'=>$product,

        'columns'=>$cols,

)); ?>

@Justinas

Instead of click you need to use live or delegate… check this post for an example - http://www.yiiframework.com/forum/index.php?/topic/13804-dynamic-deleteconfirmation-in-the-cbuttoncolumn/page__view__findpost__p__72462

Thank you, it’s working now!

You can say thank you by clicking +1 just below mdomba’s post! :] All right, all right… I’m just kidding! :] :] :]

I need to reopen and continue this topic.

Is there an easy way to extend your custom JS code, so it would NOT react on click anywhere in CGridView’s row if there would be only one row saying “No results”? Just by an accident I noticed that click reacts also if CGridView contains no data and this produces unpredictable results.

First that I can think of is to check the number of TDs… if there is only 1 there are no results…

You can add to the function




if(  1 !== $('#your-grid table tbody tr').children().length )

{

   your code here

}