4

I'm a student and working on my practical project. Its a web application which tracks google rankings for keywords and shows them as a table. Now I want to color every row green, if the current ranking is better than the previous, red if the ranking went down etc. How can I implement this in Yii with CGridView? Currently I have the following solution. In the ControllerClass I have a function

public function getCssClass($data)
{
    $cssClass;

    if('($data->current_pos>$data->prev_pos) || ($data->current_pos===null && $data->prev_pos!==null)')
    {
        $cssClass='rdown';
    }
    elseif('$data->current_pos<$data->prev_pos')
    {
        $cssClass='rup';
    }
    else
    {
        $cssClass='requal';
    }

    return $cssClass;
}

And in the view I call this function at 'rowCssClassExpression':

<?php $this->widget('zii.widgets.grid.CGridView', array(
'id'=>'keyword-grid',
'dataProvider'=>$keywordDataProvider,
'rowCssClassExpression' => $this->getCssClass($data),
'columns'=>array(
    'keyword_name',
    array(
        'name'=>'current_pos',
        'htmlOptions'=>array('style'=>'text-align: center'),
    ),
    array(
        'name'=>'prev_pos',
        'htmlOptions'=>array('style'=>'text-align: center'),
    ),
    array(
        'name'=>'top_pos',
        'htmlOptions'=>array('style'=>'text-align: center'),
    ),
    'url',
    array(
        'class'=>'CButtonColumn',
        'template'=>'{view}{delete}',
        'viewButtonUrl'=>'Yii::app()->createUrl("/keyword/view", array("id"=>$data->id))',
        'deleteButtonUrl'=>'Yii::app()->createUrl("/keyword/delete", array("id"=>$data->id))',
    ),
),
'nullDisplay'=>'-',
)); ?>

This is my table:

Keyword current previous

Keyword1 7 7

Keyword2 8 10

Keyword3 26 20

But the html result is that every row gets the class 'rdown'. I can't find my mistake :-( If someone could help and point me in the right direction I would really appreciate it.

1 Answer 1

5

'($data->current_pos>$data->prev_pos) || ($data->current_pos===null && $data->prev_pos!==null)' in your method is a string and it is always true. That's why rdown is returned. Why do you use ' to wrap the condition?

Please also note that rowCssClassExpression is a PHP expression so probably the result of your method should be wrapped in quotes:

'rowCssClassExpression' => '"' . $this->getCssClass($data) . '"',

Unfortunately this will not work too due to model's instance $data is defined within rowCssClassExpression (and evaluated for each row of the grid) but not in context of your view.

As a solution you can create getCssClass as a method of your model. Then your expression will look like this:

'rowCssClassExpression' => '$data->getCssClass()',

To specify a CSS class for each particular cell you can also look at cssClassExpression of CGridColumn class.

Sign up to request clarification or add additional context in comments.

4 Comments

Thx Ezze. Still not working. I wrapped the condition in quotes because I get no value if I do not use quotes. But still you're right. It doesn't make sense to have such a condition.
In my getCssClass() I tried: $current_pos=$data->current_pos; and returned gettype($current_pos). Result is null. $current_pos='$data->current_pos'; returns the correct values as class names in my html: 7, 8, 26. But the problem is that in the function itself before displaying in the browser $current_pos is a string containing '$data->current_pos'. So I can't use it in my if conditions. When I try to cast the var to int the result of the casting is always 0. Also if I use intval(). How do I get the value of '$data->current_pos' as an int value so I can use them in my conditions correctly?
I still believe that specifying rowCssClassExpression as $this->getCssClass($data) is wrong because $data is a model instance defined only within rowCssClassExpression that is a string property of CGridView. In your case you call $this->getCssClass($data) passing undefined $data and result of this call is considered as PHP expression to determine a CSS class (but not as CSS class itself).
So the proper way to set a row class could be: 'rowCssClassExpression' => '$this->getCssClass($data)'. But in context of this expression $this is a CGridView instance but not the controller. That's why I recommend you to move getCssClass method to your model ('rowCssClassExpression' => '$data->getCssClass()') and access this model's properties within the method using $this-> reference as usual. '$data->getCssClass()' will be evaluated as PHP expression, method getCssClass() of the model will be called then and a string result of this call will become a CSS class of your row.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.