Yii2 GridView - attribute format based on value of other attribute

2.7k Views Asked by At

I made custom currency formatter + converter based on values from database. This is how I use it in DetailView

use yii\helpers\Html;
use app\commands\AppHelper;
use yii\widgets\DetailView;
use app\models\Part;

<?= DetailView::widget([
    'model' => $model,
    'attributes' => [
        // ...
        [
            'attribute' => 'price',
            'label' => (new Part())->getAttributeLabel('price_user'),
            'format' => [
                'currency',
                AppHelper::getUserCurrencyCode(),
                [
                    'convert' => true,
                    'currencyFrom' => $model->currency->code,
                    'currencyTo' => AppHelper::getUserCurrencyCode(),
                ],
            ],
        ],
        // ...
    ],
]) ?>

In this widget I can accomplish behaviour like this: when there is numeric value, it gets formatted, if there is NULL value, usual (not-set) is printed out... Notice $model->currency->code which is data from relation, in DetailView easily accessible but I can not figure out how to get that data into formatter in GridView.

Problem is when I want to format data in GridView.

I allow NULL values on column that I need to use formatter on, so I already threw away idea of using

'value' => function ($data, $key, $index, $column) { return $data->value; }

because when NULL value is present, yii sends data like this

<span class="not-set">(not set)</span>

and either I want to let it be or set my custom value (considering different value for other columns with NULL value) and I also want to save trouble handling all those (not set) values.

Another reason is, as I noticed, that if I use 'format' => ... in attribute params, formatting happens before setting those (not set) values.

So I was thinking about somehow passing that $model->currency->code, which is data from relation, to that formatter.

Any ideas? Thanks.

1

There are 1 best solutions below

0
On

Worst case scenario I will use formatter in value dumping values that contains '<span' or NULL like this, but it is ugly and I dont like it...

EDIT: I added custom static method to format unset data. I still dont like it, but hey, it works ... :D

use yii\helpers\Html;
use app\commands\AppHelper;
use yii\grid\GridView;
use app\models\Part;

<?= GridView::widget([
    'dataProvider' => $dataProvider,
    'filterModel' => $searchModel,
    'columns' => [
        // ...
        [
            'attribute' => 'price',
            'label' => (new Part())->getAttributeLabel('price_user'),
            'value' => function ($data, $key, $index, $column) {
                return Part::requestPrice(Yii::$app->formatter->asCurrency(
                    $data->price,
                    AppHelper::getUserCurrencyCode(),
                    [
                        'precision' => 2,
                        'convert' => true,
                        'currencyFrom' => $data->currencyCode,
                        'currencyTo' => AppHelper::getUserCurrencyCode(),
                    ]));
            },
            'format' => 'raw',
        ],
        // ...
    ],
]); ?>

and in Part.php (Part model) I added method

public static function requestPrice($price)
{
    if (strpos($price, 'class') !== false || empty($price) || floatval($price) == 0)
        return '<span class="not-set">' . Yii::t('app', 'na vyžiadanie') . '</span>';
    else
        return $price;
}