Presentation of the Problem ¶
For each column of the CGridView, we can specify customized buttons : Customize Buttons in CGridWiew
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="icon-enveloppe"></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 :
<a rel="tooltip" data-toggle="tooltip" title="Send an email" href="index.php?r=users/email&id=1">
<i class="icon-envelope"></i>
</a>
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 :
Extend the class CButtonColumn ¶
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;
// Start of modification
if( isset ( $options['evaluateOptions'] ) )
{
foreach( $options['evaluateOptions'] as $key=>$value)
{
$options[$value] = $this->evaluateExpression($options[$value],array('data'=>$data,'row'=>$row));
}
unset($options['evaluateOptions']);
}
// END of modifications
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:
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.
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.
Use the new class ButtonColumn ¶
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'),
),
),
),
),
)
);
This tutorials have been inspired by Update "CGridView: Use special variable $data in the htmlOptions of a column (i.e. evaluate htmlOptions attribute)"
great !
Really helpful !
Flexible as possible.
Just one thing, I got an error and I've been thinking it was because of different versions of title value (in this example - Quotes) :
1/
'title' => '"Send an email to $data->email"',
2/
'title' => '"Send an email to $data->email',
No no no.. It does not matter.
Be careful to call the right class in view :
'class'=>'ButtonColumn',
Thanks a lot.
If you have any questions, please ask in the forum instead.
Signup or Login in order to comment.