呃,系统自带的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的显示更漂亮醒目。
好了,就这样,睡觉先!