Getting values from clicked CGridView row

The task in this post is quite simple. Obtain ID (keyField) of a record holding data for clicked CGridView row and one or more values from it’s columns. If you can/want use jQuery, this isn’t to hard job.

For first part (get ID of a record binded to clicked CGridView row) it all means to use internal jQuery function ($.fn.yiiGridView.getSelection(id)) that Yii Framework Dev Team prepared specifically for this task:

$this->widget('zii.widgets.grid.CGridView', array
(
    'id'=>'examinations-grid',
    'selectableRows'=>1,
    'selectionChanged'=>'function(id){alert($.fn.yiiGridView.getSelection(id))}',
    ...
}

Don’t forget to set also selectableRows to 1.

For second part (getting value of particular column), which can be useful, for example for displaying delete confirmation, we’re also use jQuery in a slightly magical way.

In my example, I want to display username and login of a user that is going to be deleted. For this purpose I’ve added a CButtonColumn to my CGridView, with delete button’s class set to “delete-button-that-requires-confirmation”. Of course, I had to use class, not ID, because there can be more than one delete button.

Then for each button having above class I’ve attached click event:

Yii::app()->clientScript->registerScript('admin-users-delete-confirmation',
"
    $('.delete-button-that-requires-confirmation').click(function()
    {
        var login = $(this).parent().parent().children(':nth-child(1)').text();
        var name = $(this).parent().parent().children(':nth-child(2)').text();
        var question = 'User "' + name + '" (' + login + ') will be deleted! Continue?';

        return confirm(question);
    });
");

That would be all for jQuery way. But, if you can’t or don’t want to (bad idea) use jQuery, then this task becomes a quite adventure! I wasn’t able to find ready solution, so I crafted my own. But I had to use a little bit trick. I don’t know, if this is perfect, but for me, it works like a charm.

First, I’ve added two new columns (in the beginning) to my CGridView.columns, filled them with data I need and set them to be invisible:

'columns'=>array
(
    array
    (
        'type'=>'raw',
        'headerHtmlOptions'=>array('style'=>'display: none;'),
        'htmlOptions'=>array('style'=>'display: none;'),
        'value'=>'"{{{".$data->ID."}}}"'
    ),
    array
    (
        'type'=>'raw',
        'headerHtmlOptions'=>array('style'=>'display: none;'),
        'htmlOptions'=>array('style'=>'display: none;'),
        'value'=>'"{{{".$data->PATIENT."}}}"'
    ),
    ...
)

Invisible for end-user, but not for JS script! :] Notice, that these columns are of raw type and their contents are surrounded by {{{ and }}}.

Then I modified my onclick handler attached to every row of that CGridView, so it would extract any value surround by those {{{ and }}} and return it to a proper field:

function onGridViewSelectionChange()
{               
    var inner = this.innerHTML;
    var pattern = /{{{.*?}}}/gi;
    var matches = inner.match(pattern);
    matches = matches.toString().replace(/{{{/gi, "").replace(/}}}/gi, "").split(",");

    document.getElementById("pacjent-id").value = matches[0];
    document.getElementById("pacjent-name").value = matches[1];
}

That was all. For me this solution work like a charm.

Leave a Reply