no-gutters
.row 上帶有 margin-left: -15px;margin-right: -15px; 屬性,你可以在.row 上上定義.no-gutters 屬性,從而消除這個屬性,使頁面不會額外寬出 30px,即 <div class="row no-gutters"...
$content->row(function (Row $row) {
// 啟用 no-gutters
$row->noGutters();
$row->column(9, function (Column $column) {
$column->row($this->card(['col-md-12', 20], '#4DB6AC'));
$column->row(function (Row $row) {
// 啟用 no-gutters
$row->noGutters();
$row->column(4, $this->card(['col-md-4', 30], '#80CBC4'));
$row->column(4, $this->card(['col-md-4', 30], '#4DB6AC'));
$row->column(4, function (Column $column) {
$column->row(function (Row $row) {
// 啟用 no-gutters
$row->noGutters();
$row->column(6, $this->card(['col-md-6', 30], '#26A69A'));
$row->column(6, $this->card(['col-md-6', 30], '#26A69A'));
});
});
});
});
});
效果如下
$grid->column('picture')->image();
//設定伺服器和寬高
$grid->column('picture')->image('http://xxx.com', 100, 100); // 顯示多圖
$grid->column('pictures')->display(function ($pictures) { return json_decode($pictures, true);
})->image('http://xxx.com', 100, 100);
$grid->column('state')->using([1 => '未處理', 2 => '已處理', ...])
顯示 badge 標籤
$grid->column('name')->badge();
// 設定顏色,直接傳別名
$grid->column('name')->badge('danger');
// 也可以這樣使用
$grid->column('name')->badge(Admin::color()->danger());
// 也可以直接傳顏色程式碼
$grid->column('name')->badge('#222');
布林值顯示 (bool)#
將這一列轉為 bool
值之後顯示為✓
和✗
。
$grid->column('approved')->bool();
你也可以按照這一列的值指定顯示,比如欄位的值為 Y
和 N
表示 true
和 false
$grid->column('approved')->bool(['Y' => true, 'N' => false]);
圓點字首 (dot)
透過 dot 方法可以在列文字前面加上一個帶顏色的圓點
use Dcat\Admin\Admin;
$grid->column('state')
->using([1 => '未處理', 2 => '已處理', ...])
->dot(
[
1 => 'primary',
2 => 'danger',
3 => 'success',
4 => Admin::color()->info(),
],
'primary' // 第二個引數為預設值
);
expand
方法可以把內容隱藏,點選按鈕的時候顯示在表格下一行
use Dcat\Admin\Widgets\Card;
$grid->column('content')->expand(function (Grid\Displayers\Expand $expand) {
// 設定按鈕名稱
$expand->button('詳情');
// 返回顯示的詳情
// 這裡返回 content 欄位內容,並用 Card 包裹起來
$card = new Card(null, $this->content);
return "<div style='padding:10px 10px 0'>$card</div>";
});
// 可以在閉包內返回非同步載入類的例項
$grid->post->expand(function () {
// 允許在閉包內返回非同步載入類的例項
return Post::make(['title' => $this->title]);
});
非同步載入#
定義渲染類,繼承 Dcat\Admin\Support\LazyRenderable
use App\Models\Post as PostModel;
use Dcat\Admin\Support\LazyRenderable;
use Dcat\Admin\Widgets\Table;
class Post extends LazyRenderable
{
public function render()
{
// 獲取ID
$id = $this->key;
// 獲取其他自定義引數
$type = $this->post_type;
$data = PostModel::where('user_id', $id)
->where('type', $type)
->get(['title', 'body', 'body', 'created_at'])
->toArray();
$titles = [
'User ID',
'Title',
'Body',
'Created At',
];
return Table::make($titles, $data);
}
}
使用
$grid->post->display('View')->expand(Post::make(['post_type' => 1]));
// 可以在閉包內返回非同步載入類的例項
$grid->post->expand(function () {
// 允許在閉包內返回非同步載入類的例項
return Post::make(['title' => $this->title]);
});
彈出模態框 (modal)
modal 方法可以把內容隱藏,點選按鈕的時候顯示在模態框中
use Dcat\Admin\Widgets\Card;
$grid->column('content')
->display('檢視') // 設定按鈕名稱
->modal(function ($modal) {
// 設定彈窗標題
$modal->title('標題 '.$this->username);
// 自定義圖示
$modal->icon('feather icon-x');
//$this->content指的是當前欄位的內容
$card = new Card(null, $this->content);
return "<div style='padding:10px 10px 0'>$card</div>";
});
// 也可以透過這種方式設定彈窗標題
$grid->column('content')
->display('檢視') // 設定按鈕名稱
->modal('彈窗標題', ...);
非同步載入
定義渲染類,繼承 Dcat\Admin\Support\LazyRenderable
use App\Models\Post as PostModel;
use Dcat\Admin\Support\LazyRenderable;
use Dcat\Admin\Widgets\Table;
class Post extends LazyRenderable
{
public function render()
{
// 獲取ID
$id = $this->key;
// 獲取其他自定義引數
$type = $this->post_type;
$data = PostModel::where('user_id', $id)
->where('type', $type)
->get(['title', 'body', 'body', 'created_at'])
->toArray();
$titles = [
'User ID',
'Title',
'Body',
'Created At',
];
return Table::make($titles, $data);
}
}
使用
$grid->post->display('View')->modal('Post', Post::make(['post_type' => 2]));
// 可以在閉包內返回非同步載入類的例項
$grid->post->modal(function ($modal) {
$modal->title('自定義彈窗標題');
// 允許在閉包內返回非同步載入類的例項
return Post::make(['title' => $this->title]);
});
非同步載入工具表單#
<?php
namespace App\Admin\Forms;
use Dcat\Admin\Contracts\LazyRenderable;
use Dcat\Admin\Traits\LazyWidget;
use Dcat\Admin\Widgets\Form;
class UserProfile extends Form implements LazyRenderable
{
use LazyWidget;
public function handle(array $input)
{
// 接收外部傳遞引數
$type = $this->payload['type'] ?? null;
return $this->response()->success('儲存成功');
}
public function form()
{
// 接收外部傳遞引數
$type = $this->payload['type'] ?? null;
$this->text('name', trans('admin.name'))->required()->help('使用者暱稱');
$this->image('avatar', trans('admin.avatar'))->autoUpload();
$this->password('old_password', trans('admin.old_password'));
$this->password('password', trans('admin.password'))
->minLength(5)
->maxLength(20)
->customFormat(function ($v) {
if ($v == $this->password) {
return;
}
return $v;
})
->help('請輸入5-20個字元');
$this->password('password_confirmation', trans('admin.password_confirmation'))
->same('password')
->help('請輸入確認密碼');
}
}
使用
$grid->user->display('View')->modal(UserProfile::make(['type' => 1]));
進度條 (progressBar)
$grid->rate->progressBar();
//設定顏色,預設`primary`,可選`danger`、`warning`、`info`、`primary`、`success`
$grid->rate->progressBar('success');
// 設定進度條尺寸和最大值
$grid->rate->progressBar('success', 'sm', 100);
showTreeInDialog#
showTreeInDialog 方法可以把一個帶有層級關係的陣列呈現為樹形彈窗,比如許可權就可以用此方法展示
// 查出所有的許可權資料
$nodes = (new $permissionModel)->allNodes();
// 傳入二維陣列(未分層級)
$grid->permissions->showTreeInDialog($nodes);
// 也可以傳入閉包
$grid->permissions->showTreeInDialog(function (Grid\Displayers\DialogTree $tree) use (&$nodes, $roleModel) {
// 設定所有節點
$tree->nodes($nodes);
// 設定節點資料欄位名稱,預設"id","name","parent_id"
$tree->setIdColumn('id');
$tree->setTitleColumn('title');
$tree->setParentColumn('parent_id');
// $this->roles 可以獲取當前行的欄位值
foreach (array_column($this->roles, 'slug') as $slug) {
if ($roleModel::isAdministrator($slug)) {
// 選中所有節點
$tree->checkAll();
}
}
});
陣列操作
如果當前列輸出的是陣列,可以直接鏈式呼叫 Illuminate\Support\Collection 方法。
比如 tags 列是從一對多關係取出來的陣列資料:
$grid->tags();
array (
0 =>
array (
'id' => '16',
'name' => 'php',
'created_at' => '2016-11-13 14:03:03',
'updated_at' => '2016-12-25 04:29:35',
),
1 =>
array (
'id' => '17',
'name' => 'python',
'created_at' => '2016-11-13 14:03:09',
'updated_at' => '2016-12-25 04:30:27',
),
)
呼叫 Collection::pluck() 方法取出陣列的中的 name 列
$grid->tags()->pluck('name');
array (
0 => 'php',
1 => 'python',
),
比如 images 欄位是儲存多圖片地址陣列的 JSON 格式字串型別:
$grid->images();
// "['foo.jpg', 'bar.png']"
// 鏈式方法呼叫來顯示多圖
$grid->images()->display(function ($images) {
return json_decode($images, true);
})->map(function ($path) {
return 'http://localhost/images/'. $path;
})->image();
擴充套件類
如果列顯示邏輯比較複雜,可以透過擴充套件類來實現。
擴充套件類 app/Admin/Extensions/Popover.php:
<?php
namespace App\Admin\Extensions;
use Dcat\Admin\Admin;
use Dcat\Admin\Grid\Displayers\AbstractDisplayer;
class Popover extends AbstractDisplayer
{
public function display($placement = 'left')
{
Admin::script("$('[data-toggle=\"popover\"]').popover()");
return <<<EOT
<button type="button"
class="btn btn-secondary"
title="popover"
data-container="body"
data-toggle="popover"
data-placement="$placement"
data-content="{$this->value}"
>
彈出提示
</button>
EOT;
}
}
然後在 app/Admin/bootstrap.php 註冊擴充套件類:
use Dcat\Admin\Grid\Column;
use App\Admin\Extensions\Popover;
Column::extend('popover', Popover::class);
Copy
然後就能在 model-grid 中使用了:
$grid->desciption()->popover('right');
切換行操作按鈕顯示方式
全域性預設的行操作按鈕顯示方式可以透過配置引數 admin.grid.grid_action_class 引數進行配置,目前支援的行操作按鈕顯示方式有以下兩種:
Dcat\Admin\Grid\Displayers\DropdownActions 下拉選單方式
Dcat\Admin\Grid\Displayers\Actions 圖示展開方式
Dcat\Admin\Grid\Displayers\ContextMenuActions 滑鼠右鍵顯示下拉選單 (Since v1.4.5)
...
'grid' => [
/*
|--------------------------------------------------------------------------
| The global Grid action display class.
|--------------------------------------------------------------------------
*/
'grid_action_class' => Dcat\Admin\Grid\Displayers\DropdownActions::class,
],
...
Copy
在控制器中切換顯示方式
use Dcat\Admin\Grid;
public function grid()
{
return Grid(new Model(), function (Grid $grid) {
$grid->setActionClass(Grid\Displayers\Actions::class);
...
});
}
獲取行序號 (index)
序號從 0 開始計算
// 在 display 回撥中使用
$grid->column('序號')->display(function () {
return $this->_index + 1;
});
// 在行操作 action 中使用
$grid->actions(function ($actions) {
$index = $this->_index;
...
});
獲取當前行資料
可以透過傳入的 $actions 引數來獲取當前行的資料:
use Dcat\Admin\Grid;
$grid->actions(function (Grid\Displayers\Actions $actions) {
// 當前行的資料陣列
$rowArray = $actions->row->toArray();
// 當前行的某個欄位的資料
$email = $actions->row->email;
// 獲取當前行主鍵值
$id = $actions->getKey();
});
新增自定義按鈕
如果有自定義的操作按鈕,可以透過下面的方式新增:
use Dcat\Admin\Grid;
$grid->actions(function (Grid\Displayers\Actions $actions) {
// append一個操作
$actions->append('<a href=""><i class="fa fa-eye"></i></a>');
// prepend一個操作
$actions->prepend('<a href=""><i class="fa fa-paper-plane"></i></a>');
});
新增複雜操作按鈕
如果有比較複雜的操作,可以參考下面的方式:
先定義行操作類繼承 Dcat\Admin\Grid\RowAction
{tip} 動作類更詳細的用法,請參考動作基本使用以及資料表格動作。
<?php
namespace App\Admin\Extensions;
use Dcat\Admin\Grid\RowAction;
class CheckRow extends RowAction
{
/**
* 返回欄位標題
*
* @return string
*/
public function title()
{
return 'Check row';
}
/**
* 新增JS
*
* @return string
*/
protected function script()
{
return <<<JS
$('.grid-check-row').on('click', function () {
// Your code.
console.log($(this).data('id'));
});
JS;
}
public function html()
{
// 獲取當前行資料ID
$id = $this->getKey();
// 獲取當前行資料的使用者名稱
$username = $this->row->username;
// 這裡需要新增一個class, 和上面script方法對應
$this->setHtmlAttribute(['data-id' => $id, 'email' => $username, 'class' => 'grid-check-row']);
return parent::html();
}
}
然後新增操作:
$grid->actions(new CheckRow());
// 也可以透過這種方式新增
$grid->actions(function (Grid\Displayers\Actions $actions) {
$actions->append(new CheckRow());
});
操作按鈕需要與 API 互動
如果你的操作類需要與後臺介面互動,則可以在你的操作類中加上 handle 方法,這樣就可以很方便的在同一個類裡面處理完所有邏輯
{tip} 動作類更詳細的用法,請參考動作基本使用以及資料表格動作。
<?php
namespace App\Admin\RowActions;
use Dcat\Admin\Grid\RowAction;
use Illuminate\Http\Request;
use Illuminate\Database\Eloquent\Model;
class Copy extends RowAction
{
protected $model;
public function __construct(string $model = null)
{
$this->model = $model;
}
/**
* 標題
*
* @return string
*/
public function title()
{
return 'Copy';
}
/**
* 設定確認彈窗資訊,如果返回空值,則不會彈出彈窗
*
* 允許返回字串或陣列型別
*
* @return array|string|void
*/
public function confirm()
{
return [
// 確認彈窗 title
"您確定要複製這行資料嗎?",
// 確認彈窗 content
$this->row->username,
];
}
/**
* 處理請求
*
* @param Request $request
*
* @return \Dcat\Admin\Actions\Response
*/
public function handle(Request $request)
{
// 獲取當前行ID
$id = $this->getKey();
// 獲取 parameters 方法傳遞的引數
$username = $request->get('username');
$model = $request->get('model');
// 複製資料
$model::find($id)->replicate()->save();
// 返回響應結果並重新整理頁面
return $this->response()->success("複製成功: [{$username}]")->refresh();
}
/**
* 設定要POST到介面的資料
*
* @return array
*/
public function parameters()
{
return [
// 傳送當前行 username 欄位資料到介面
'username' => $this->row->username,
// 把模型類名傳遞到介面
'model' => $this->model,
];
}
}
使用
use App\Models\User;
$grid->actions([new Copy(User::class)]);
// 也可以透過這種方式新增
$grid->actions(function (Grid\Displayers\Actions $actions) {
$actions->append(new Copy(User::class));
});
表單彈窗
請參考文件工具表單 - 彈窗
多對多#
users 和 roles 表透過中間表 role_users 產生多對多關係
CREATE TABLE `users` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(190) COLLATE utf8_unicode_ci NOT NULL,
`password` varchar(60) COLLATE utf8_unicode_ci NOT NULL,
`name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `users_username_unique` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
CREATE TABLE `roles` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
`slug` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `roles_name_unique` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
CREATE TABLE `role_users` (
`role_id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
KEY `role_users_role_id_user_id_index` (`role_id`,`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
對應的資料模和資料倉儲分別為:
User 模型
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
public function roles()
{
return $this->belongsToMany(Role::class);
}
}
Role 模型
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Role extends Model
{
public function users()
{
return $this->belongsToMany(User::class);
}
}
資料倉儲
<?php
namespace App\Admin\Repositories;
use App\Models\User as UserModel;
use Dcat\Admin\Repositories\EloquentRepository;
class User extends EloquentRepository
{
protected $eloquentClass = UserModel::class;
}
同樣這裡支援上述的三種方式關聯資料,限於篇幅這裡不再重複寫所有用法
use App\Admin\Repositories\User;
// 關聯 role 表資料
$grid = Grid::make(new User('roles'), function (Grid $grid) {
$grid->id('ID')->sortable();
$grid->username();
$grid->name();
$grid->roles()->pluck('name')->label();
$grid->created_at();
$grid->updated_at();
});
本作品採用《CC 協議》,轉載必須註明作者和本文連結