CGridview conditional delete button

12,324

Solution 1

use 'visible' parameter -

 'buttons'=>array
    (
        'delete' => array
        (
            'label'=>'Delete',
            //other params
            'visible'=>!Yii::app()->user->checkAccess('admin'),
        ),

Solution 2

'visible'=>'$data->status=="draft" || Yii::app()->user->checkAccess("admin")'

Solution 3

You can also use anonymous function if PHP >= 5.3

'visible'=>function($row, $data) {
    return Yii::app()->user->checkAccess('admin') || 'draft' == $data->status;
}

Solution 4

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.

Share:
12,324
zuups
Author by

zuups

Updated on June 19, 2022

Comments

  • zuups
    zuups almost 2 years

    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!

  • zuups
    zuups about 12 years
    Thanks, it works (if I put 'visible' value in single quotes :)
  • Mick MacCallum
    Mick MacCallum over 11 years
    To improve the quality of your post, please include why/how your answer solves the problem.
  • Pavel Dubinin
    Pavel Dubinin over 9 years
    @Mukesh Soni right, this is misleading. Please put quotes around that expression in your answer, currently its wrong
  • guidod
    guidod over 9 years
    This won't work for the draft use case. See answers involving $data
  • Gerhard Liebenberg
    Gerhard Liebenberg over 7 years
    I think it must be function($data, $row) and not function($row, $data).