开始GridView

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

于是GridView出现了,一个有细节、够稳定的表格渲染挂件。

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

在学习GridView挂件之前,我们需要先了解GridView的结构,看下图。

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

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。

准备阶段

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

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的使用方法。

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。

要注意:A6、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,你可以重新指定。

yii2 GirdView使用全教程的更多相关文章

  1. Yii2框架RESTful API教程(二) - 格式化响应,授权认证和速率限制

    之前写过一篇Yii2框架RESTful API教程(一) - 快速入门,今天接着来探究一下Yii2 RESTful的格式化响应,授权认证和速率限制三个部分 一.目录结构 先列出需要改动的文件.目录如下 ...

  2. Yii2框架RESTful API教程(一) - 快速入门

    前不久做一个项目,是用Yii2框架写一套RESTful风格的API,就去查了下<Yii 2.0 权威指南 >,发现上面写得比较简略.所以就在这里写一篇教程贴,希望帮助刚接触Yii2框架RE ...

  3. Docker最全教程之使用Tencent Hub来完成CI(九)

    使用Tencent Hub来完成CI 关于Tencent Hub Tencent Hub是腾讯出品的DevOps服务.主要提供多存储格式的版本管理,支持Docker Image.Binary.Helm ...

  4. Docker最全教程——从理论到实战(八)

    在本系列教程中,笔者希望将必要的知识点围绕理论.流程(工作流程).方法.实践来进行讲解,而不是单纯的为讲解知识点而进行讲解.也就是说,笔者希望能够让大家将理论.知识.思想和指导应用到工作的实际场景和实 ...

  5. Docker最全教程——从理论到实战(七)

    在本系列教程中,笔者希望将必要的知识点围绕理论.流程(工作流程).方法.实践来进行讲解,而不是单纯的为讲解知识点而进行讲解.也就是说,笔者希望能够让大家将理论.知识.思想和指导应用到工作的实际场景和实 ...

  6. Docker最全教程——从理论到实战(六)

    托管到腾讯云容器服务 托管到腾讯云容器服务,我们的公众号“magiccodes”已经发布了相关的录屏教程,大家可以结合本篇教程一起查阅.   自建还是托管? 在开始之前,我们先来讨论一个问题——是自建 ...

  7. Docker最全教程——从理论到实战(五)

    往期内容链接 Docker最全教程——从理论到实战(一) Docker最全教程——从理论到实战(二) Docker最全教程——从理论到实战(三) Docker最全教程——从理论到实战(四) 本篇教程持 ...

  8. Docker最全教程——从理论到实战

    Docker最全教程——从理论到实战(一) Docker最全教程——从理论到实战(二) Docker最全教程——从理论到实战(三) Docker最全教程——从理论到实战(四) Docker最全教程—— ...

  9. Docker最全教程

    摘自雪雁大佬的博客,地址:https://www.cnblogs.com/codelove/default.html 目录: Docker最全教程——从理论到实战(一) Docker最全教程——从理论 ...

随机推荐

  1. jetBrains 插件开发第一课-- 在主菜单栏新增一个菜单

    环境搭建完了,接下来可以开始写代码了: 1.新建 plugin 项目 2.编辑 plugin.xml,修改一下里面的插件名那些信息,该文件的配置项可以看这里:plugin.xml 其中比较关键的有一个 ...

  2. git clone 无权限

    错误提示: remote: Coding.net Tips : [You have no permission to access this repo.] fatal: unable to acces ...

  3. 「Python」10个python项目

    1. Pillow. Pillow是由Alex Clark以及其他贡献者实现的“友好版”的PIL.PIL即Python Imaging Library,作者是Fredrik Lundh及其他开发者.A ...

  4. mysql 查询小demo

    两张表的的结构如下,需求是写出从one表到two表和从two表到one表的查询转换. create table student_one( name varchar(50) default '' not ...

  5. 怎样在hibernate的HQL语句中使用mysql 的自定义函数?

    问题:怎样在hibernate中使用mysql的函数? 1.hibernate支持原生态的sql语句查询,使用session.createSQLQuery()创建查询对象: 2.怎样在hql中使用my ...

  6. 【Java】将字符串转化为整数

    前几天面试遇到这个问题:在Java中如何将字符串转化为整数,当时too young too naive,随便回答了一下.今天跑去看Java源码中paresInt函数的写法,Oh my god!其实不看 ...

  7. Google Map API 应用实例说明

    目录 Google Map API 1基础知识 1.1 Google 地图 API 概念 1.2 Google 地图的"Hello, World" 1.2.1 加载 Google ...

  8. CF540 C BFS 水

    '.'->'X' 前者走后变成后者,后者除了是终点不能再走.初始位置是X很傻的以为这样从初始点走出去后初始位置就变成不能走了,实际上是还能走一次的. 其他就是BFS,路上记得把路变成X就好了 太 ...

  9. JVM调优总结(3):垃圾回收面临的问题

    如何区分垃圾 上面说到的“引用计数”法,通过统计控制生成对象和删除对象时的引用数来判断.垃圾回收程序收集计数为0的对象即可.但是这种方法无法解决循环引用.所以,后来实现的垃圾判断算法中,都是从程序运行 ...

  10. DHTML中window的使用

    window对象是对浏览器窗口进行操作的对象.以下列出一些常用的对象(三级为对象的方法.属性) |-navigator:是对浏览器信息进行操作的对象 |-history:包含用户浏览过的url信息 | ...