I want the delete button to be active only in certain condition in CGgridView
CButtonColumn
(or make a custom delete button) e g if user=='admin'
or status=='draft'
. Any ideas? Thanks!
4 Answers
use 'visible' parameter -
'buttons'=>array
(
'delete' => array
(
'label'=>'Delete',
//other params
'visible'=>!Yii::app()->user->checkAccess('admin'),
),

- 6,646
- 3
- 30
- 37
-
2Thanks, it works (if I put 'visible' value in single quotes :) – zuups Feb 24 '12 at 18:09
-
@Mukesh Soni right, this is misleading. Please put quotes around that expression in your answer, currently its wrong – Pavel Dubinin Sep 07 '14 at 13:14
-
1This won't work for the draft use case. See answers involving $data – guidod Oct 09 '14 at 11:42
'visible'=>'$data->status=="draft" || Yii::app()->user->checkAccess("admin")'

- 91
- 1
- 2
-
1To improve the quality of your post, please include why/how your answer solves the problem. – Mick MacCallum Oct 06 '12 at 06:27
You can also use anonymous function if PHP >= 5.3
'visible'=>function($row, $data) {
return Yii::app()->user->checkAccess('admin') || 'draft' == $data->status;
}

- 3,168
- 2
- 21
- 25
-
I think it must be function($data, $row) and not function($row, $data). – Gerhard Liebenberg Oct 05 '16 at 17:49
As zuups states in Mukesh post, you have to use single quotes! And user1584901 is right with the answer, in the case the status is a property of the model instance. So,
'visible'=>'$data->status=="draft" || Yii::app()->user->checkAccess("admin")',
is correct. (Explanation at the bottom)
I want to add some interesting things you can do as well. For example, consider a user with assets. In this case I would want to add the delete button only to users that don't have any assets.
In this case, you can make a relation in the user model such as
'haveAssets' = array(self::STAT,'Asset', 'asset_id','select'=>'1')
Which will return 1 if the user has assets, or 0 otherwise. And define the visible parameter as
'visible' => '!$data->haveAssets',
The reason all this works (as asked by 0x7fffffff) is because Yii uses the string defined in visible to apply it to the evaluateExpression function inside the function that render the buttons (renderButton).
From: https://github.com/yiisoft/yii/blob/1.1.14/framework/zii/widgets/grid/CButtonColumn.php line 337
protected function renderButton($id,$button,$row,$data)
{
if (isset($button['visible']) && !$this->evaluateExpression($button['visible'],array('row'=>$row,'data'=>$data)))
return;
Which is defined in the CComponent class: https://github.com/yiisoft/yii/blob/1.1.14/framework/base/CComponent.php line 607
public function evaluateExpression($_expression_,$_data_=array())
{
if(is_string($_expression_))
{
extract($_data_);
return eval('return '.$_expression_.';');
}
else
{
$_data_[]=$this;
return call_user_func_array($_expression_, $_data_);
}
}
So basically what happens is that the evaluateExpression function will make available the variables $data (which is the model instance for the row in question) and $row (all this by using the extract function) and evaluate your string expression as php code. So any mention to $data or $row will use the variable already set by the evaluteExpression function in this scope. That's why you can use the respective model instance of the respective row (as $data->status, or $data->haveAssets from the examples). Notice that the string should be a expression that returns a boolean to determine the visibility of the button.
And the reason the strings should be in single quotes is that while using double quotes, php will assume that any string that starts with $ is a variable and will try to replace it with that variable value. Since, in your scope the $data variable is meaningless (or could be defined) it will throw an error or replace it misleadingly. Using single quotes you prevent having this behaviour.

- 166
- 9