Adding custom button to grid view in Yii2

Here is a quick guide on how to add, in Yii2, a custom button to GridView’s ActionColumn, with standard or with customised URL.

First, you have to modify buttons property of your ActionColumn. In Yii 2 we no longer play with putting PHP code into string, that is later eval‘d because eval is pure evil, right? :> Instead, you need to write a closure.

The simplest way of writing it, is to copy and modify ActionColumn::initDefaultButtons() method's code. For example:

'buttons' => [
    'see' => function ($url, $model, $key) {
        $options = [
            'title' => Yii::t('yii', 'See in frontend'),
            'aria-label' => Yii::t('yii', 'See'),
            'data-pjax' => '0',
        ];
        return Html::a('<span class="glyphicon glyphicon-asterisk"></span>', $url, $options);
    }
],

Note, that in above code you don’t have access to buttonOptions property, just as it is done in ActionColumn::initDefaultButtons() method's code, and this is generally OK. The buttonOptions property is for setting options only to default buttons (as docs stands).

You have to care yourself for applying the same options to your custom buttons (if this is needed, because in default implementation, shown here, it isn’t).

You, of course, have to modify template property, to “tell” GridAction, that it is supposed to render extra custom button. Therefore, the entire code of this column could look like that:

[
    'class' => 'yiigridActionColumn',
    'template' => '{view} {update} {delete} {see}',
    'contentOptions' => [
        'style' => 'width: 10%; text-align: center;'
    ],
    'buttons' => [
        'see' => function ($url, $model, $key) {
            $options = [
                'title' => Yii::t('yii', 'See in frontend'),
                'aria-label' => Yii::t('yii', 'See'),
                'data-pjax' => '0',
            ];

            return Html::a('<span class="glyphicon glyphicon-asterisk"></span>', $url, $options);
        }
    ],
],

This, basic, implementation will auto-create URL for your button and it will use button name (see in this example) as action name and current (or the one set in controller property) controller to generate URL for each custom button.

Therefore, you’ll end up with something like http://127.0.0.1/appname/web/controller/see?id=1.

If you need to have really custom URL, pointing out to another controller (but just for this one button), another application or even away to the Internet, you’ll have two options.

One, a bit less professional, is to simply override $url value, that your custom button’s closure function is fed, with URL generated using other function parameters, like that:

'see' => function ($url, $model, $key) {
    $options = [
        'title' => Yii::t('yii', 'See in frontend'),
        'aria-label' => Yii::t('yii', 'See'),
        'data-pjax' => '0',
    ];
    $url = yiihelpersUrl::toRoute(['lab/index', 'id' => $key]);

    return Html::a('<span class="glyphicon glyphicon-asterisk"></span>', $url, $options);
}

The other, a bit professional way, is to modify the urlCreator property, as it is shown in Kartik’s example from Yii Forum (a bit modified version). And Url::toRoute() method for generating URLs:

'urlCreator' => function ($action, $model, $key, $index) {
    if ($action === 'see') {
        return yiihelpersUrl::toRoute(['lab/index', 'id' => $key]);
    } else {
        return Url::toRoute([$action, 'id' => $model->id]);
    }
}

Unfortunately, this example is not working. It only generates URL for custom button, not for default ones.

Sources:

Leave a Reply