常常有人問yii2的GridView配置問題,最近羣裏也有人問到,我想是時候發佈一個教程了。php
咱們採用的是yii2.0.14版本,爲了學習方便,以問答式書寫。css
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 |
在A系列中咱們先說說GridView中column的使用方法。yii
當咱們只須要$dataProvider每一個對象的某些屬性的時,則必需要指定columns屬性,代碼以下
try { echo GridView::widget([ 'dataProvider' => $dataProvider, 'columns'=>[ 'id', 'username', 'province', 'city', 'created_at' ] ]); }catch(\Exception $e){ // todo }
結果以下
在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種最靈活。
在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也能實現此題的需求。
經過對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 }
從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來取消此列排序功能,以下圖。
到如今你已經知道了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類解決這個問題。
在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中的showFooter的時候,忽然PhpStorm自動關聯出一個footerRowOptions,這是個什麼東西那?
footerRowOptions是GridView的屬性,它控制着tfoot的tr標籤屬性,簡單點說,你最後在tfoot上每一個單元格看到的效果是footerRowOptions + footerOptions 的結合體(就style而言)。
好比針對上面的例子咱們在配置下footerRowOptions
'footerRowOptions'=>['style'=>'font-size:20px;']
則你會發現黃色字體變成了20px。
要注意:A六、A7和A8中的這些xxxOptions所能控制的是標籤的屬性,不僅僅是style。
從A7中咱們知道了GridView的showFooter,它決定這table是否顯示tfoot信息,除此以外show家族還有一些其餘成員。
這個片斷咱們說下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等等,針對於不一樣類型列的講解,要後續放出。
接下來咱們進入B系列,B系列的重點在講解GridView。
默認狀況下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}。
在一個表格中每列都有不一樣的做用,有的是數據類型的、有的是複選框類型,具體有5種
經過GridView能夠設置一列的默認類型,固然你能夠針對特殊的類單獨指定其class。
try { echo GridView::widget([ 'dataProvider' => $dataProvider, 'columns'=>[ ], 'dataColumnClass'=>"yii\grid\DataColumn" ]); }catch(\Exception $e){ // todo }
咱們能夠經過設置GridView的caption屬性來實現table的caption功能,做爲table用途很是有用。
try { echo GridView::widget([ 'dataProvider' => $dataProvider, 'columns'=>[ ], 'caption'=>"會員列表" ]); }catch(\Exception $e){ // todo }
效果圖以下
固然不用多說,GridView也提供了captionOptions屬性來讓你控制caption的屬性。
這兩個屬性有的開發者可能會混淆,接下來我用一張圖讓你瞬間明白。
就是說GridView渲染的時候首先弄出來一個div容器,這是這個GridView的表明,接下來在此容器內放各類元素,好比{summary}、{items}等等。
如今你會改table的樣式類了麼?
咱們在A8中講了footerRowOptions的用法,headerRowOptions的用法和它同樣,只不過它管理的是thead下tr的屬性。
學會了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對象這是一對很是靈活的屬性,它們接收一個匿名函數。分別表示在渲染了一行以前和以後發生點什麼?固然具體發生什麼由你來決定。
要記住的是,匿名函數返回的結果也會做爲一行歸入到渲染過程,好比當咱們遇到奇數的時候就在此行下面添加一行,能夠以下代碼
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 }
很是好,獲得了咱們想要的結果
很細節的兩個小屬性
不知不覺寫了3000多字,本想一篇完成GridView的講解,如今看來比較困難,畢竟還有不少類型的列要去研究分享,仍是變成專題吧,接下來我會對每一個列作單獨的分析,但願對你有用。
感謝閱讀 更多Yii深度文章分享