表格
建议编辑通过表格布局,您可以轻松地以结构化和有序的方式显示大量数据。只需指定您想要在表格中包含的字段,表格布局将处理其余的工作,包括排序、过滤和分页。您还可以通过设置各种选项来自定义表格的外观,例如表格标题、行值等。无论您是在显示用户列表、产品、订单或任何其他数据,表格布局都是以清晰简洁的方式呈现数据的强大而灵活的工具。
要创建新的表格布局,您可以使用以下 Artisan 命令:
php artisan orchid:table PatientListLayout
示例:
namespace App\Orchid\Layouts;
use Orchid\Screen\TD;
use Orchid\Screen\Layouts\Table;
class PatientListLayout extends Table
{
/**
* 数据源。
*
* 从查询中获取的键名。
* 其结果将是表格的元素。
*
* @var string
*/
protected $target = 'patients';
/**
* @return TD[]
*/
protected function columns() : iterable
{
return [
TD::make('name'),
TD::make('created_at')->sort(),
];
}
}
表格还支持通过简短语法编写而无需创建类:
use Orchid\Support\Facades\Layout;
use Orchid\Screen\TD;
Layout::table('clients', [
TD::make('name'),
TD::make('created_at')->sort(),
]);
单元格介绍
表格只是一个通用包装器,您需要为其指定 TD
类。旨在创建单个单元格。
use Orchid\Screen\TD;
TD::make('last_name');
make
方法是主要方法,设置数组中的键名和显示名称。
TD::make('last_name', '姓氏');
列标题以其原始 HTML 内容呈现。这使您可以灵活地在标题中直接包含丰富格式或特殊字符。只需记住确保任何动态内容都是安全和经过清理的,以保持界面的安全和精致。
对齐
内容对齐控制可以使用 align
方法进行控制:
TD::make('last_name')->align(TD::ALIGN_LEFT);
TD::make('last_name')->align(TD::ALIGN_CENTER);
TD::make('last_name')->align(TD::ALIGN_RIGHT);
排序
选择排序应在 query
屏幕中完成,对于模型,您可以使用自动 http
排序和过滤
要启用此列的活动排序,必须指定 sort
方法:
TD::make('last_name')->sort();
过滤
在构建简单表格时,使用单独的过滤器可能显得过于繁琐。因此,您可以直接在列标题上方显示过滤字段。
它只会定义可见部分。您可以自己指定过滤逻辑或依赖于“自动 HTTP 过滤”。您可以在 “Eloquent Filters” 页面了解更多信息。
要添加字段,请调用 filter 方法并传递您想要显示的类实例:
TD::make('SKU')->filter(Input::make()->mask('A-999999'));
注意:无需指定字段名称。它将由列名称自动传递和覆盖。
可以使用 Select 过滤多个值,并使用可选的第二个过滤参数。默认情况下,它允许过滤给定值中的任何/所有值。
TD::make('color')->filter(TD::FILTER_SELECT, [
'red' => '红色',
'green' => '绿色',
]);
在使用过滤器时,可以使用 filterValue()
方法,该方法允许您修改显示的过滤值。例如,您可以将 ID 值替换为显示名称。以下是使用 filterValue()
方法的示例:
TD::make('id')->filterValue(function ($value) {
$user = User::find($value);
return $user->name;
})
传递给函数的 $value
值将包含应用的过滤值。
宽度
您可以使用 width
方法控制单元格的宽度:
TD::make('last_name')->width('100px');
显示/隐藏
默认情况下,用户可以为自己隐藏任何列,但您可以通过指定以下内容来禁止这样做:
TD::make('last_name')->cantHide();
也可以默认隐藏,但可以根据用户请求显示。
TD::make('last_name')->defaultHidden();
数据输出
在某些情况下,您可能需要显示组合数据,为此目的可以使用 render
方法。它实现了根据函数生成单元格的能力:
TD::make('full_name')
->render(fn($user) => e($user->first_name . ' ' . $user->last_name)),
注意。 返回的字符串不会被转义!您需要使用
e()
助手或使用Blade
视图自行处理。
回调函数必须返回任何字符串值:
TD::make('full_name')
->render(fn($user) => view('blade_template', [
'user' => $user,
])),
请注意,您可以使用字段和操作:
use Orchid\Screen\Actions\Link;
TD::make()
->render(fn ($user) => Link::make($user->last_name)->route('platform.user.edit', $user)),
有时您希望在单个列中显示更多元素,例如更多按钮。为此,您可以使用 Group
:
use Orchid\Screen\Actions\Link;
use Orchid\Screen\Fields\Group;
TD::make()
->render(fn($user) => Group::make([
Link::make('显示')->route('platform.user.show', $user),
Link::make('编辑')->route('platform.user.edit', $user),
])),
例如,为每行显示一个复选框以进行批量操作:
TD::make()
->render(fn(User $user) => CheckBox::make('users[]')
->value($user->id)
->placeholder($user->name)
->checked(false)
),
有时可能需要从 query
屏幕获取值,而不是仅依赖于 target
。您可以按如下方式获取值:
use Orchid\Screen\Actions\Link;
TD::make('price')
->render(fn ($product) => $product->price + $this->query->get('tax')),
使用循环变量
$loop
变量将在 render
闭包函数的第二个参数中可用。此变量提供了一些有用的信息,例如当前循环索引以及这是否是循环的第一次或最后一次迭代:
TD::make()->render(fn (Model $model, object $loop) => $loop->index),
$loop
变量包含许多其他有用的属性,您可以在 Laravel 文档中找到。
使用组件
复杂或动态数据在 render 方法中指定可能显得繁琐或令人不知所措。因此,单元格支持使用 Laravel 组件进行渲染。它允许您提取显示逻辑,并且可以重用。
例如,有一个 Order
模型,根据状态,我们可以在组件中显示不同的描述。这比直接在视图中指定内容或为此类处理创建特定区域要好得多。
namespace App\View\Components;
use Illuminate\View\Component;
use App\Models\Order;
class OrderShortInformation extends Component
{
public function __construct(
public readonly Order $order
) {}
/**
* 获取状态描述。
*
* @return string
*/
public function status(): string
{
return match ($this->order->status) {
Order::STATUS_PROCESS => __('处理中'),
Order::STATUS_PAID => __('已支付'),
Order::STATUS_CANCELLATION => __('取消'),
Order::STATUS_REFUND => __('退款'),
default => __('未知'),
};
}
/**
* 获取表示组件的视图/内容。
*
* @return \Illuminate\View\View|\Closure|string
*/
public function render(): \Illuminate\View\View|\Closure|string
{
return view('components.order.short-information');
}
}
要在单元格中使用组件,您必须传递它:
use App\View\Components\OrderShortInformation;
TD::make('status')->component(OrderShortInformation::class);
组件将接收整行作为其第一个参数,而不仅仅是单元格数据。
因此,如果您在组件中使用深度注入,必须指定变量的名称。
public function __construct(Application $application, Order $order, int $limit = 300)
{
$this->order = $order;
// ...
}
其他附加参数,例如限制。您可以按以下方式指定:
TD::make('status')->component(OrderShortInformation::class, [
'limit' => 100
]);
自定义组件值
这与上面使用组件非常相似,只是前面的示例获取了一个对象。但这并不总是必要的,有时只需要处理一个值。
为此,您需要添加一个新方法,该方法默认情况下只接收单元格值而不接收其他信息。例如,我想以特定格式显示值:
namespace App\View\Components;
use Illuminate\View\Component;
class Numeric extends Component
{
/**
* @var float
*/
public float $value;
/**
* 创建新的组件实例。
*
* @param float $value
* @param int $decimals
* @param string|null $decimal_separator
* @param string|null $thousands_separator
*/
public function __construct(
float $value,
int $decimals = 0,
?string $decimal_separator = ".",
?string $thousands_separator = ","
) {
$this->value = number_format($value, $decimals, $decimal_separator, $thousands_separator);
}
/**
* 获取表示组件的视图/内容。
*
* @return \Illuminate\Contracts\View\View|\Closure|string
*/
public function render()
{
return <<<'blade'
{{ $value }}
blade;
}
}
然后表格调用可能如下所示:
TD::make('price')->asComponent(Numeric::class);
// 1,235
也可以使用附加参数:
TD::make('price')->asComponent(Numeric::class, [
'decimals' => 2,
'decimal_separator' => ',',
'thousands_separator' => ' ',
]);
// 1 234,56
表格选项
您可以指定表格为空时要显示的文本,指定方法:
/**
* @return string
*/
protected function iconNotFound(): string
{
return 'table';
}
/**
* @return string
*/
protected function textNotFound(): string
{
return __('此视图中没有记录');
}
/**
* @return string
*/
protected function subNotFound(): string
{
return '';
}
如果表格行对您来说不够对比鲜明,那么您可以启用 striped
模式:
/**
* @return bool
*/
protected function striped(): bool
{
return true;
}
您可以通过以下方法动态更改表格分页中显示的链接数量:
/**
* 在当前页面链接的每一侧显示的链接数量。
*
* @return int
*/
protected function onEachSide(): int
{
return 3;
}
添加总计行
在表格底部添加汇总行,为此您需要定义 total
方法并描述所需的单元格。例如:
public function total():array
{
return [
TD::make('total')
->align(TD::ALIGN_RIGHT)
->colspan(2)
->render(fn () => '总计:'),
TD::make('total_count')
->align(TD::ALIGN_RIGHT),
TD::make('total_active_count')
->align(TD::ALIGN_RIGHT),
];
}
此行将忽略基于 query
屏幕结果的指定 target
:
public function query(): array
{
return [
'total_active_count' => '$93 960',
'total_count' => '$103 783',
// ...
];
}