Yii2的GridView使用大全 --- 18个问答

常常有人问yii2的GridView配置问题,最近群里也有人问到,我想是时候发布一个教程了。php

咱们采用的是yii2.0.14版本,为了学习方便,以问答式书写。css

开始GridView

GridView主要是为了实现表格复用,尤为咱们作后台的时候,你发现表单和表格占据了大部分页面,而表格的样式又是高度的统一,那么若是有这样一个挂件,传入数据集自动渲染表格该多好。html

因而GridView出现了,一个有细节、够稳定的表格渲染挂件。编程

一般状况下GridView是和各类dataProvider配合使用,针对于yii2框架中的dataProvider我以前写过一篇文章,你能够看下,这将有助于你对GridView的学习。小谈yii2中3个数据提供者及与GridView的搭配使用数组

在学习GridView挂件以前,咱们须要先了解GridView的结构,看下图。浏览器

简单的说,一个GridView由N个column(列)组成,而每一个列里有本身的header、content和footer操做,这在GridView的代码中有所体现yii2

try {
    echo GridView::widget([
        'dataProvider' => $dataProvider,
        
        'columns'=>[
            'id',
            'created_at:datetime:生成时间',
            [
                'label'=>'会员名',
                'attribute'=>'username',
                'format'=>'text'
            ],
        ]
    ]);
}catch(\Exception $e){
    // todo
}

固然yii2已经作的至关细节,你能够不写columns,GridView会根据dataProvider自动渲染出每一列,接下来咱们开始问答区域,经过一问一答来深度了解GridView。app

准备阶段

为了问答进行的顺利,咱们模拟了一个数据表做为结果集的提供源。框架

id username province city created_at updated_at Sex
1 abei 黑龙江 黑河 1514201852 1528707743 1
2 周全 吉林 长春 1528115243 1528115243 1
3 柏鑫 吉林 松原 1528180018 1528255890 1
4 张楠 辽宁 沈阳 1528265883 1528265883 0

Column

在A系列中咱们先说说GridView中column的使用方法。yii

A1. 请渲染出id、username、province、city和sex。

当咱们只须要$dataProvider每一个对象的某些属性的时,则必需要指定columns属性,代码以下

try {
    echo GridView::widget([
        'dataProvider' => $dataProvider,
        
        'columns'=>[
            'id',
            'username',
            'province',
            'city',
            'created_at'
        ]
    ]);
}catch(\Exception $e){
    // todo
}

结果以下

A2.我想更改列的头部内容

在A1中咱们发现每一列的头部是英文,如今想改为中文,有三个方法

方法1 更改对应模型中的attributeLabels方法

// app\models\User

class User extends \yii\db\ActiveRecord {
	
    public function attributeLabels(){
        return [
            'id' => 'ID',
            'username' => '用户名',
            'province' => '省',
            'city' => '城市',
            'created_at' => '新建时间',
            'updated_at' => '最近更新',
            'sex' => '性别',
        ];
    }       
}

当咱们从新设置了attributeLabels方法后,对应的GridView会自动去拿取。

方法2 设置一个column的label属性,以下代码

try {
    echo GridView::widget([
        'dataProvider' => $dataProvider,
        
        'columns'=>[
            'username:text:用户名'
        ]
    ]);
}catch(\Exception $e){
    // todo
}

能够经过设置列的label属性实现,就像 username:text:用户名,用英文冒号:分隔,分别是属性名、格式以及label。

方法3 使用GridView的自定义属性,以下代码

try {
    echo GridView::widget([
        'dataProvider' => $dataProvider,
        
        'columns'=>[
            [
                'label'=>'用户名',
                'attribute'=>'username'
            ]
        ]
    ]);
}catch(\Exception $e){
    // todo
}

上面3种方法均可以,从1-3愈来愈灵活,固然代码量也愈来愈大,第1种最简单,第3种最灵活。

A3.我不要时间戳

在A2中,咱们看到新建时间这一列的内容居然直接出现了时间戳,怎么变成对应的时间那?关于这个问题其实也有两种方法。

方法1 设置column的format属性

try {
    echo GridView::widget([
        'dataProvider' => $dataProvider,
        
        'columns'=>[
            'created_at:datetime'
        ]
    ]);
}catch(\Exception $e){
    // todo
}

方法2 经过传递一个数组类型的column并设置其value来实现,以下代码

try {
    echo GridView::widget([
        'dataProvider' => $dataProvider,
        
        'columns'=>[
            [
                'attribute'=>'created_at',
                'value'=>function($model){// 形参为此行记录对象
                    return date("Y-m-d H:i:s",$model->created_at);
                }
            ]
        ]
    ]);
}catch(\Exception $e){
    // todo
}

从A3的方法1和方法2来看,其实方法1更可能是方法2的快捷方式,所以咱们经过设置数组类型column的format属性等于datetime也能实现此题的需求。

A4.我想定义一个属性叫省市,将省和市字段内容合并

经过对A2和A3的学习,我想你已经知道能够经过数组类型的column来解决这个,没错,以下代码

try {
    echo GridView::widget([
        'dataProvider' => $dataProvider,
        
        'columns'=>[
            [
                'label'=>'省市',
                'value'=>function($model){
                    return "{$model->province}-{$model->city}";
                }
            ]
        ]
    ]);
}catch(\Exception $e){
    // todo
}

value 属性表明此单元格的数据内容,将结果返回便可,就像结果图同样。

可是问题出现了,我但愿省市一列按照省属性来排序,怎么办?只须要指定attribute便可,这也是咱们控制列排序的一种方法。

try {
    echo GridView::widget([
        'dataProvider' => $dataProvider,
        
        'columns'=>[
            [
                'label'=>'省市',
                'attribute'=>'province',
                'value'=>function($model){
                    return "{$model->province}-{$model->city}";
                }
            ]
        ]
    ]);
}catch(\Exception $e){
    // todo
}

A5.如何控制列排序?

从A4咱们知道经过设置column的attribute属性控制是否排序,可是attribute的本意并不在此,所以咱们标准的去掉排序或设置排序的方法是经过其enableSorting属性实现的。

try {
    echo GridView::widget([
        'dataProvider' => $dataProvider,
        
        'columns'=>[
            [
                'label'=>'省市',
                'attribute'=>'province',
                'enableSorting'=>false,
                'value'=>function($model){
                    return "{$model->province}-{$model->city}";
                }
            ]
        ]
    ]);
}catch(\Exception $e){
    // todo
}

默认enableSorting为true,能够经过设置为false来取消此列排序功能,以下图。

A6.列的样式如何控制?

到如今你已经知道了5个使用GridView的技巧,咱们继续,在A6中咱们尝试改变表格某一列的样式。针对于列样式,GridView提供了3个属性,分别为headerOptions、contentOptions和footerOptions。

如今咱们来作一个需求,将省市这一列个性化,列的头部编程红色,列的内容编程蓝色,以下

try {
    echo GridView::widget([
        'dataProvider' => $dataProvider,
        
        'columns'=>[
            [
                'label'=>'省市',
                'attribute'=>'province',
                'enableSorting' => false,
                'value'=>function($model){
                    return "{$model->province}-{$model->city}";
                },
                'headerOptions' => ['style'=>'color:red'],
                'contentOptions' => ['style'=>'color:blue'],
            ]
        ]
    ]);
}catch(\Exception $e){
    // todo
}

是的,使用这一列的headerOptions和contentOptions便可

有个要注意的地方,咱们使用浏览器的f12看看标注颜色的列。

你看到了,headerOptions和contentOptions直接做用到了th和td标签,为其增长相似于style等属性,所以若是你的th或td标签中还有其余的html标签,直接定义style就没法生效了,此时能够经过css类解决这个问题。

A7.关于GridView中footerOptions的使用。

在A6中咱们说GridView的列有一个footerOptions属性,那么这个属性是干吗用的那?从单词上分析是控制列footer的属性(好比样式等等),可是footer在哪里???在哪里在哪里?

须要先设置GridView的showFooter等于true才能够。才能够才能够。

try {
    echo GridView::widget([
        'dataProvider' => $dataProvider,
        
        'columns'=>[
            [
                'label'=>'省市',
                'attribute'=>'province',
                'enableSorting' => false,
                'value'=>function($model){
                    return "{$model->province}-{$model->city}";
                },
                'headerOptions' => ['style'=>'color:red'],
                'contentOptions' => ['style'=>'color:blue'],
                'footerOptions'=>['style'=>'color:yellow']
            ]
        ],
        'showFooter'=>true
    ]);
}catch(\Exception $e){
    // todo
}

在showFooter=true的天空下,列的footerOptions才能自由飞翔。

从原理上说,'showFooter'=>true的结果是让table出现了下面代码

<tfoot>
   <tr>
   	<td></td>
   	<td></td>
   	<td></td>
   <tr> 
</tfoot>

所以每列的footerOptions就控制着在tfoot中这一列对应的td。

A8.footerRowOptions你是干毛用的?

在咱们大摇大摆的用着A8中的showFooter的时候,忽然PhpStorm自动关联出一个footerRowOptions,这是个什么东西那?

footerRowOptions是GridView的属性,它控制着tfoot的tr标签属性,简单点说,你最后在tfoot上每一个单元格看到的效果是footerRowOptions + footerOptions 的结合体(就style而言)。

好比针对上面的例子咱们在配置下footerRowOptions

'footerRowOptions'=>['style'=>'font-size:20px;']

则你会发现黄色字体变成了20px。

要注意:A六、A7和A8中的这些xxxOptions所能控制的是标签的属性,不仅仅是style。

A9.showFooter的你们族

从A7中咱们知道了GridView的showFooter,它决定这table是否显示tfoot信息,除此以外show家族还有一些其余成员。

  • showHeader 能够控制table的头部是否显示,默认显示。
  • showOnEmpty 当数据为空的时候,table框架是否存在,默认不存在。

A10.魔术师visible的戏法

这个片断咱们说下GridView列的visible属性,此属性默认为true表明此列显示,经过设置visible属性能够隐藏一列,这种隐藏非css的display:none,而是在渲染表格的时候就去掉了此列。

你可能会问,若是我要使用visible来隐藏一列,我不写这一列不就行了么?

是的,你的思路没错,可是visible是能够传递一个表达式,实现逻辑判断,好比下面的需求当1号管理员登陆的时候能够看到省市一列。

try {
    echo GridView::widget([
        'dataProvider' => $dataProvider,
        
        'columns'=>[
            [
                'label'=>'省市',
                'attribute'=>'province',
                'enableSorting' => false,
                'value'=>function($model){
                    return "{$model->province}-{$model->city}";
                },
                'visible'=>(Yii::$app->admin->id === 1)
            ]
        ],
        'showFooter'=>true
    ]);
}catch(\Exception $e){
    // todo
}

A1-A10 咱们重点说的是GridView每列的公共属性,这并非所有,针对于不一样类型的列还有会其余的属性,好比DataColumn、ActionColumn、CheckboxColumn等等,针对于不一样类型列的讲解,要后续放出。


GridView

接下来咱们进入B系列,B系列的重点在讲解GridView。

B1 关于布局layout

默认状况下GridView的布局以下图

这个布局来自于GridView的layout属性,咱们能够改变这个模板,好比要去掉summary。

try {
    echo GridView::widget([
        'dataProvider' => $dataProvider,
        
        'columns'=>[
            
        ],
        'layout'=>"{items}\n{pager}"
    ]);
}catch(\Exception $e){
    // todo
}

layout内有5个可使用的值,分别为{summary}、{errors}、{items}、{sorter}和{pager}。

B2.指定列默认的类型 dataColumnClass

在一个表格中每列都有不一样的做用,有的是数据类型的、有的是复选框类型,具体有5种

  1. ActionColumn
  2. CheckboxColumn
  3. DataColumn
  4. RadioButtonColumn
  5. SerialColumn

经过GridView能够设置一列的默认类型,固然你能够针对特殊的类单独指定其class。

try {
    echo GridView::widget([
        'dataProvider' => $dataProvider,
        
        'columns'=>[
            
        ],
        'dataColumnClass'=>"yii\grid\DataColumn"
    ]);
}catch(\Exception $e){
    // todo
}

B3.caption属性

咱们能够经过设置GridView的caption属性来实现table的caption功能,做为table用途很是有用。

try {
    echo GridView::widget([
        'dataProvider' => $dataProvider,
        'columns'=>[
            
        ],
        'caption'=>"会员列表"
    ]);
}catch(\Exception $e){
    // todo
}

效果图以下

固然不用多说,GridView也提供了captionOptions属性来让你控制caption的属性。

B4.tableOptions和options属性

这两个属性有的开发者可能会混淆,接下来我用一张图让你瞬间明白。

就是说GridView渲染的时候首先弄出来一个div容器,这是这个GridView的表明,接下来在此容器内放各类元素,好比{summary}、{items}等等。

  • options 控制着div容器的属性,默认添加一个class="grid-view"
  • tableOptions 控制着{items}表格的属性,默认为其添加一个 class="table table-striped table-bordered"

如今你会改table的样式类了么?

B5.一堆好基友 headerRowOptions 和 footerRowOptions

咱们在A8中讲了footerRowOptions的用法,headerRowOptions的用法和它同样,只不过它管理的是thead下tr的属性。

B6.rowOptions

学会了B5,你可能看着rowOptions一眼识破,没错它的目的就是管理tbody下的每一个tr,可是它更强大,除了直接接收一个数组外还能传入匿名函数。

你能够融入你的逻辑,好比如今咱们要用rowOptions实现隔行换色的功能,来吧。

try {
    echo GridView::widget([
        'dataProvider' => $dataProvider,
        'columns'=>[
            
        ],
        'rowOptions'=>function($model,$key, $index){
            if($index%2 === 0){
                return ['style'=>'background:red'];
            }
        }
    ]);
}catch(\Exception $e){
    // todo
}

目的达到,看效果

对于rowOptions接收的匿名行数的4个形参,这里说明一下

  • $model: 当前被渲染的对象
  • $key: 当前对象的逐渐
  • $index: 针对于当前页面,从0开始,逐行加1
  • $grid: GridView对象

B7. beforeRow和afterRow

这是一对很是灵活的属性,它们接收一个匿名函数。分别表示在渲染了一行以前和以后发生点什么?固然具体发生什么由你来决定。

要记住的是,匿名函数返回的结果也会做为一行归入到渲染过程,好比当咱们遇到奇数的时候就在此行下面添加一行,能够以下代码

try {
    echo GridView::widget([
        'dataProvider' => $dataProvider,
        'tableOptions' => ['class'=>'table table-bordered'],
        'columns'=>[
            'id',
            'username:text:用户名',
            .....
        ],
        'afterRow'=>function($model,$key, $index,$grid){
            if(($index+1)%2 != 0){
                return "<tr><td colspan='4'>我是基数</td></tr>";
            }
        }
    ]);
}catch(\Exception $e){
    // todo
}

很是好,获得了咱们想要的结果

B8. 两个小盆友placeFooterAfterBody & emptyCell

很细节的两个小属性

  • placeFooterAfterBody 当咱们要显示footer的时候,placeFooterAfterBody属性决定将此html放到table的什么位置,默认放到header后面,你能够选择placeFooterAfterBody=true来让footer放到body后面。此功能是在yii2.0.14才支持的。
  • emptyCell 又是一个小细节,若是一个单元格为空,用什么字符填充那?默认是 &nbsp,你能够从新指定。

小结

不知不觉写了3000多字,本想一篇完成GridView的讲解,如今看来比较困难,毕竟还有不少类型的列要去研究分享,仍是变成专题吧,接下来我会对每一个列作单独的分析,但愿对你有用。

感谢阅读 更多Yii深度文章分享

相关文章
相关标签/搜索