Yii 1.1: Cgridview: Use Special Variable $Data In The Options Of A Button (I.e. Evaluate Options Attribute)

Hi, I would like to submit an article for the wiki. But I can’t since I don’t have enough post in the forum … :rolleyes:

It’s inspired by this article :

http://www.yiiframework.com/wiki/314/cgridview-use-special-variable-data-in-the-htmloptions-of-a-column-i-e-evaluate-htmloptions-attribute/#hh1

But instead of evaluating htmlOptions attribute of a column, it will evaluate options attribute of a button.

Here the proposition (without any wiki marks):

[size="4"]Presentation of the Problem[/size]

For each column of the CGridView, we can specify customized buttons :

http://www.yiiframework.com/wiki/106/using-cbuttoncolumn-to-customize-buttons-in-cgridview/

Let’s take the example of the above article to display an email button next to a delete button:


array

(

    'class'=>'CButtonColumn',

    'template'=>'{email}{delete}',

    'buttons'=>array

    (

        'email' => array

        (

            'label'=>'<i class="fa fa-eye"></i>',

            'url'=>'Yii::app()->createUrl("users/email", array("id"=>$data->id))',

            'options' => array(

                                'rel' => 'tooltip',

                                'data-toggle' => 'tooltip', 

                                'title'       => '"Send an email', ),

            ),

    ),

),

For each one of those customized buttons, we can specify options. Those options will be the attribute of the button’s link. In the above example, we use the options to use font awesome envelope icon instead of an picture (as realtebo suggested it the comments). So the button html code will look like this :

[html]

<a rel="tooltip" data-toggle="tooltip" title="Send an email" href="index.php?r=users/email&id=1">

<i class="icon-envelope"></i>

</a>

[/html]

Now we might want to use $data in the declaration of the options attribute, which is normally not possible, to generate for example the title "Send an email to foo@bar.com", where foo@bar.com is the email of the data model for the current row, i.e. $data->email.

That is, we want to be able to use:


            'options' => array(

                                'rel' => 'tooltip',

                                'data-toggle' => 'tooltip', 

                                'title'       => '"Send an email to $data->email"', ),

            ),



Here’s a way to accomplish this…

[size="4"]Extend the class CButtonColumn[/size]

Under protected/components/ create the file ButtonColumn.php with the following content:




<?php

/**

 * ButtonColumn class file.

 * Extends {@link CButtonColumn}

 */


class ButtonColumn extends CButtonColumn

{




	/**

	 * Renders a link button.

	 * @param string $id the ID of the button

	 * @param array $button the button configuration which may contain 'label', 'url', 'imageUrl' and 'options' elements.

	 * See {@link buttons} for more details.

	 * @param integer $row the row number (zero-based)

	 * @param mixed $data the data object associated with the row

	 */

	protected function renderButton($id,$button,$row,$data)

	{

		if (isset($button['visible']) && !$this->evaluateExpression($button['visible'],array('row'=>$row,'data'=>$data)))

  			return;

		$label=isset($button['label']) ? $button['label'] : $id;

		$url=isset($button['url']) ? $this->evaluateExpression($button['url'],array('data'=>$data,'row'=>$row)) : '#';

		$options=isset($button['options']) ? $button['options'] : array();

		if(!isset($options['title']))

			$options['title']=$label;


		// HACK

		if($options['evaluateOptions']) 

		{

			foreach( $options['evaluateOptions'] as $key=>$value) 

			{

        	            $options[$value] = $this->evaluateExpression($options[$value],array('data'=>$data,'row'=>$row));

        	        }

	

			unset($options['evaluateOptions']);

		}

		// END HACK !!!


		if(isset($button['imageUrl']) && is_string($button['imageUrl']))

			echo CHtml::link(CHtml::image($button['imageUrl'],$label),$url,$options);

		else

			echo CHtml::link($label,$url,$options);

	}

}



Originally the options attribute was used without any evalution, like this:




$options=isset($button['options']) ? $button['options'] : array();

...

echo CHtml::link($label,$url,$options);



What we do differently from the original is:

  1. We introduce the new array variable $options[‘evaluateOptions’]. This array contains a list of options, to control whether the evaluation of an option attribute should be done or not.

  2. If an option is not set in this array, nothing changes. If one or many option is set in this array, so those options and only those ones will be evaluated.

[size="4"]Use the new class ButtonColumn [/size]

We can use this new class like this:


$this->widget(

    'bootstrap.widgets.CGridView',

    array(

        'dataProvider' => $emails,

        'columns' => array(

	    array('name'=>'destination_email', 'header'=>'Destination Email'),             

         ),


         array

         (

             // Here, we use our new class ButtonColumn instead of CButtonColumn

             'class'=>'ButtonColumn',

             'template'=>'{email}{delete}',

             'buttons'=>array

             (

                 'email' => array

                 (

                     'label'=>'Send an e-mail to this user',

                     'url'=>'Yii::app()->createUrl("users/email", array("id"=>$data->id))',

                     'options' => array(

                                         'rel' => 'tooltip',

                                         'data-toggle' => 'tooltip', 


                                         // Here, we use the $data

                                         'title'       => '"Send an email to $data->email',

                                         // Here, we specify that we want title to be evaluated

                                         'evaluateOptions' => array('title'),


                                       ),

                 ),

             ),

        ),

    )

);



It will look like that :

5675

extend-cbutton-options.jpg

[size="4"]SO ? [/size]

This derserves an article in the wiki ? Doesn’t it ?

Ok, I put it in the wiki :

http://www.yiiframework.com/wiki/714/yii-1-1-cgridview-use-special-variable-data-in-the-options-of-a-button-i-e-evaluate-options-attribute/