Yii2的相关学习记录,alert等美化、confirm异步、session中的flash及小部件的使用(六)

呃,系统自带的alert、confirm等弹出框实在是难看,做为一个颜控,这能忍?php

这里我用的是kartik-v/yii2-dialog,这个是基于bootstrap3-dialog这个来作了一些经常使用alert、confirm和dialog的小部件封装,固然了,本质上仍是bootstrap3-dialog,能够用原生的方法,原生方法的用法点这里,而bootstrap3-dialog又是基于bootstrap3的modals作的封装。嗯,基本关系就是这样。在搜索这个相关知识时,常常会看到有人提到bootbox,这个一样是流行的一个美化插件,基本原理相似,用法稍微不一样,在packagist搜索yii2 bootbox会发现也有人为Yii2作了集成(或者本身集成也行,后面会讲到),一样值得推荐。css

按照说明安装,最好是按照github的说明,由于最新的通常都会在这里先更新。composer中要用@dev。能够看这里的说明,若是不成功,先composer self-update,再试下,当初安装时也是各类报错不行,后来忽然就行了。稍微注意的是confirm,dialog调用时要求必须写回调,不然就报错。git

仍是蛮漂亮的。可是像是Yii框架Gridview自带的confirm(像是删除按钮),点击时仍是原生的,由于它的源码就是用的confirm命令,好在Yii框架提供了方法,可让咱们覆盖confirm方法。具体可以下操做:github

一、咱们能够先看下在vendor/yiisoft/yii2/assets/yii.js文件中的confirm方法:注释中就能够看到,能够用yii.confirm来重写此设置。web

 /**
    * Displays a confirmation dialog.
    * The default implementation simply displays a js confirmation dialog.
    * You may override this by setting `yii.confirm`.
    * @param message the confirmation message.
    * @param ok a callback to be called when the user confirms the message
    * @param cancel a callback to be called when the user cancels the confirmation
    */
    confirm: function (message, ok, cancel) {
        if (confirm(message)) {
            !ok || ok();
        } else {
            !cancel || cancel();
        }
    },

二、那咱们就重写,能够在backend/web/js中新建confirm.js文件,而后从新,可参照此文章,这是设置bootbox的,并且版本有点过期,不过下方的评论有最新方法。而咱们的设置与此原理是一致的,只不过是改为kartik-v/yii2-dialog所需求的参数样式:bootstrap

yii.confirm = function (message, ok, cancel) {
    krajeeDialog.confirm(message,function(data){
        if (data) {
            !ok || ok();
        } else {
            !cancel || cancel();
        }
    });
    // confirm will always return false on the first call
    // to cancel click handler
    return false;
}

三、咱们须要注册此js,能够在backend/assets/Appasset.php中添加上方的js文件:数组

class AppAsset extends AssetBundle
{
    public $basePath = '@webroot';
    public $baseUrl = '@web';
    public $css = [
        'css/site.css',
    ];
    public $js = [
        'js/confirm.js',//就是这里了
    ];
    public $depends = [
        'yii\web\YiiAsset',
        'yii\bootstrap\BootstrapAsset',
    ];
}

这样一来,在点击删除按钮便会发现能够调用了:yii2

因为咱们用的是kartik-GridView,它的两个功能展现所有记录和导出csv等的提示,都是用的原生的confirm,强迫症的咱们能忍吗?好吧,我忍了,这里只给出改的思路,尤为是只懂基础js的我来讲,先把时间放在其它地方吧。(2017.03.31注:3.1.2版本以上的kartik-GridView中会自动带有yii2-dialog来提示,因此下面修改js什么的没什么用了。)cookie

在改以前,首先咱们须要明确kartik-v/yii2-dialog的confirm(bootbox一样)和原生confirm的不一样。原生confirm是同步的,而kartik-v/yii2-dialog的confirm方法是异步回调的。这致使原生的confirm能够直接这样写:session

function abc(){
    return window.confirm('123');//confirm点击确认返回true,取消返回false,不点击就等着用户点击    
}
if(abc()){
    alert('456');//点击是,会弹出alert弹窗
}

而若是你用kartik-v/yii2-dialog的confirm也这样写,则永远不会弹窗,由于是异步回调的,不会去等你点击。

function abc(){
    krajeeDialog.confirm('123',function(result){
        if(result){
            return true;
        }else{
            return false;
        }
    });
}
if(abc()){
    alert('456');//因为是异步回调,因此无论点不点都不会弹窗
}

可能有人会想(好比我)这样写行不行?不行,不支持这样的写法,bootstrap3-dialog中这样写返回的是窗口有没有open。

if(krajeeDialog.confirm('123',function(result){}){
    return true;
}else{
    return false;      
}

因此要想在kartik-v/yii2-dialog的confirm中执行alert,只能将alert放在回调函数中:

function abc(){
    krajeeDialog.confirm('123',function(result){
        if(result){
            alert('456');
        }else{
           //do something
        }
    });
}

 以上的不一样,再加上是在vendor中修改有违原则啊(拿出来很费劲,又是继承什么的,而导出csv的js没找到相似yii.js那样覆盖的方法,只能从新写引入什么的),也是我不想改源码的缘由。坑爹。好吧,下面继续说怎么改:

一、{toggleData}显示所有记录,它的调用confirm是在vendor/kartik-v/yii2-grid/GridView.php中的getToggleDataScript方法,咱们修改return就能够:

$url=Url::current([$this->_toggleDataKey => $tag]);//先定义须要跳转的url
return "\$('#{$this->_toggleButtonId}').on('{$event}',function(e){
    e.preventDefault();//先阻止点击事件
    krajeeDialog.confirm('{$msg}',function(data){
        if (data) {
            window.location.href='{$url}';//点击是则跳转
        }
    });
    //下面这条是原来的方法
    // if(!window.confirm('{$msg}')){e.preventDefault();}
});";

二、{export}中的导出提示,是在vendor/kartik-v/yii2-grid/assets/js/kv-grid-export.js中:这个就麻烦了,感受须要重写关联的notify方法和listenClick方法。谁写完了,麻烦告诉一声吧。

kvConfirm: function (msg) {             
    try {
        return window.confirm(msg);//调的这个
    }
    catch (err) {
        return true;
    }
}

上面就这样吧。

下面说下session中的flash,咱们通常建立完成等操做时,须要给点提示是完成了仍是怎么着。在Yii中有自带flash方法来实现,可点击这里查看,其实在adminLTE这个后台框架中已集成了Alert小部件,咱们能够在backend/views/layout/content.php中发现此小部件的调用<?= Alert::widget() ?>,这是咱们只须要在controller中添加setFlash方法,那么就能在view中接收到:

  public function actionCreate()
    {
        $model = new User();

        if ($model->load(Yii::$app->request->post()) && $model->save()) {
            $session = Yii::$app->session;//session
            $session->setFlash('success', '建立成功');//添加flash
            return $this->redirect(['index']);
        } else {
            return $this->render('create', [
                'model' => $model,
            ]);
        }
    }

捕捉到的:(adminLTE的alert样式颜色就是这么深,而Yii框架自带的颜色虽然浅,可是与此后台框架的颜色也不搭配)

进一步扩展就是,若是是成功的提示,那我5s后能够隐藏,那能够这样设置,在backend/views/layout/content.php中添加下面渐隐的js代码

<?php //这是一段,在显示后定里消失的JQ代码
    $this->registerJs("
        $('.alert-success').animate({opacity: 1.0}, 5000).fadeOut('slow');
    ");  
?> 

唉?为何忽然说到flash,明显先后文不统一吗,差评!主要是,既然有alert形式的flash,那固然也能够用弹窗的方式来展现啊。kartik-v/yii2-dialog虽然有alert、dialog功能,可是在这里都和我想要的不太同样,因此咱们直接调用原生的方法来写,主要的方法是这样:(下面有详细封装)

var dialogShow=BootstrapDialog.show({
    type:BootstrapDialog.TYPE_SUCCESS, 
    title:'提示消息',
    message:'建立成功,3s后自动关闭',
    size:BootstrapDialog.SIZE_SMALL,
    buttons:[
        {
            label: '关闭',
            action: function(dialogItself){
                dialogItself.close();
            }
        }
    ]
});

咱们固然能够直接在index.php中写,可是东西有点多,最好封装一下,好吧,那就参照Alert来写一个Popup的widget来用吧:(一些介绍点这里),在common/widgets中新建Popup.php,直接贴代码吧。因为只是注册js,没有返回值什么的,因此没有用到run()方法。

 1 <?php
 2 
 3 namespace common\widgets;
 4 
 5 class Popup extends \yii\bootstrap\Widget
 6 {
 7     /**
 8      * 样式数组
 9      * @var [type]
10      */
11     public $popupTypes = [
12         'default'   => 'BootstrapDialog.TYPE_DEFAULT',
13         'info'  => 'BootstrapDialog.TYPE_INFO',
14         'primary' => 'BootstrapDialog.TYPE_PRIMARY',
15         'success'    => 'BootstrapDialog.TYPE_SUCCESS',
16         'warning' => 'BootstrapDialog.TYPE_WARNING',
17         'danger' => 'BootstrapDialog.TYPE_WARNING'
18     ];
19     /**
20      * 尺寸数组
21      * @var [type]
22      */
23     public $sizeTypes=[
24         'nomal'=>'BootstrapDialog.SIZE_NORMAL',
25         'small'=>'BootstrapDialog.SIZE_SMALL',
26         'wide'=>'BootstrapDialog.SIZE_WIDE',
27         'large'=>'BootstrapDialog.SIZE_LARGE'
28 
29     ];
30     /**
31      * 标题
32      * @var [type]
33      */
34     public $title;
35     /**
36      * 尺寸
37      * @var [type]
38      */
39     public $size;
40 
41     public function init()
42     {
43         parent::init();
44         //默认标题
45         if ($this->title === null) {
46             $this->title = '消息提示';
47         }
48         //默认样式
49         if ($this->size===null || !isset($this->sizeTypes[$this->size])){
50             $this->size='small';
51         }
52 
53         $session = \Yii::$app->session;
54         $flashes = $session->getAllFlashes();
55 
56         $view = $this->getView();
57 
58         foreach ($flashes as $type => $data) {
59             if (isset($this->popupTypes[$type])) {
60                 $data = (array) $data;
61                 foreach ($data as $i => $message) {
62                     $view->registerJs("
63                         var dialogShow=BootstrapDialog.show({
64                             type:".$this->popupTypes[$type].",
65                             title:'".$this->title."',
66                             message:'".$message."',
67                             size:".$this->sizeTypes[$this->size].",
68                             buttons:[
69                                 {
70                                     label: '关闭',
71                                     action: function(dialogItself){
72                                         dialogItself.close();
73                                     }
74                                 }
75                             ]
76                         });
77                     ");
78                     // 若是是成功,须要增长3s后自动关闭,其他警告等则不须要
79                    if($type=='success'){
80                         $view->registerJs("
81                             setTimeout(function(){ dialogShow.close() }, 3000);
82                         ");
83                    }
84                 }
85 
86                 $session->removeFlash($type);
87             }
88         }
89     }
90 }
太长隐藏

而后在backend/views/layout/content.php引用小部件:

use common\widgets\Popup;
<?= Popup::widget([
    'title'=>'消息',
    'size'=>'small'//参数不写会有默认值
]) ?>

 看下效果:若是是success,则会自动消失。

那弹出框Popup和提示Alert最大区别是,当存在addFlash方法时,Alert能够依次排列显示多个,而弹出框Popup则会重复覆盖显示,不太友好。固然了在不用addFlash方法时弹出框Popup的显示更漂亮醒目。

好了,就这样,睡觉先!

相关文章
相关标签/搜索