Escape from Default's Yii2 Delete Confirm Box

You are viewing revision #2 of this wiki article.
This is the latest version of this article.
You may want to see the changes made in this revision.

« previous (#1)

If you started playing with Yii2's new GridView, you will soon realize that some things have improved quite a lot, but I am sure its going to be a bit confusing at first glance when you try to modify certain javascript behaviors like for example, its delete confirmation dialog box.

I am sure there will be others finding better solutions, but on my case, I found the following quite simple to execute. On this article I am going to show you how to use the excellent library "BootboxJS" to display our confirmation box.  So, the first thing you need to do is to download that library and place it on your "web/js" folder (I am using the basic template application structure for the example).

Override Yii.js Module

The first thing we need to do is to override the methods "confirm" and "allowAction" on the yii.js module. The reason is that the module is the responsible of handling the click events of our rendered ActionColumn action links.

In order to override its methods, lets create a javascript file named "main.js" (for example) and we are going to place it on our "web/js" folder. These are the contents:

yii.allowAction = function ($e) {
    var message = $e.data('confirm');
    return message === undefined || yii.confirm(message, $e);
};
yii.confirm = function (message, $e) {
    bootbox.confirm(message, function (confirmed) {
        if (confirmed) {
            yii.handleAction($e);
        }
    });
    // confirm will always return false on the first call
    // to cancel click handler
    return false;
}

Bootbox confirm by default doesn't have a title, to add a title (modal-title) to your confirm box, use this code instead:

yii.allowAction = function ($e) {
        var message = $e.data('confirm');
        return message === undefined || yii.confirm(message, $e);
    };
    yii.confirm = function (message, $e) {
        bootbox.confirm({
            title: 'Confirm',
            message: 'Are you sure?',            
            callback: function (result) {
                if (result) {
                    yii.handleAction($e);
                }
            }
        });
        // confirm will always return false on the first call
        // to cancel click handler
        return false;
    }

The way the module comes by default is by using the native browser's confirm dialog window that obviously stops the asynchronous execution of Javascript, but when you try to use "bootbox::confirm" method, that is not happening as the callback of the plugin does not return until the user clicks on one of the dialog's buttons.

Thats the reason we override the "yii::confirm", because we require the reference of the DOM object in order to call "yii::handleAction" properly. But is "yii::allowAction" the method who receives that reference, and thats why we had to override that method as well.

With this solution, the "yii::allowAction" will return false the first time, but "bootbox::confirm" will react according to user's action. Thats the price you pay, but it works.

Register Your Assets

There is one last thing to do, modify our application's asset bundle to register both "bootbox.min.js" and "main.js" script files.

For that we go to our "assets/AppAsset.php" file and write the following:

namespace backend\assets;

use yii\web\AssetBundle;

class AppAsset extends AssetBundle
{
    public $basePath = '@webroot';
    public $baseUrl = '@web';
    public $css = ['css/site.css'];
    // register the library first after our
    // script
    public $js = ['js/bootbox.min.js', 'js/main.js'];
    public $depends = [
        'yii\web\YiiAsset',
        'yii\bootstrap\BootstrapAsset',
    ];
}

And thats it, next time we click on the delete action of our grid, we will see a beautiful Bootstrap Confirm dialog.

bootbox dialog