Skip to content
全部文档

自定义组件

向 schema 插入 Blade 视图

可使用「view」组件向 schema 任意插入 Blade 视图:

php
use Filament\Schemas\Components\View;

View::make('filament.schemas.components.chart')

这假定你已有 resources/views/filament/schemas/components/chart.blade.php 文件。

可通过 viewData() 方法向该视图传递数据:

php
use Filament\Schemas\Components\View;

View::make('filament.schemas.components.chart')
    ->viewData(['data' => $data])

渲染组件的子 schema

可向组件的 schema() 方法传入子 schema 组件数组:

php
use Filament\Forms\Components\TextInput;
use Filament\Schemas\Components\View;

View::make('filament.schemas.components.chart')
    ->schema([
        TextInput::make('subtotal'),
        TextInput::make('total'),
    ])

在 Blade 视图中,可使用 $getChildSchema() 函数渲染组件的 schema()

blade
<div>
    {{ $getChildSchema() }}
</div>

在 Blade 视图中访问另一个组件的状态

在 Blade 视图中,可使用 $get() 函数访问 schema 中另一个组件的状态:

blade
<div>
    {{ $get('email') }}
</div>

TIP

除非表单字段是 响应式的,否则字段值变化时 Blade 视图不会刷新,只有在下一次会向服务器发起请求的用户交互时才会刷新。若需要响应字段值的变化,应使用 live()

在 Blade 视图中访问 Eloquent 记录

在 Blade 视图中,可使用 $record 变量访问当前 Eloquent 记录:

blade
<div>
    {{ $record->name }}
</div>

在 Blade 视图中访问当前操作

在 Blade 视图中,可使用 $operation 变量访问当前操作,通常为 createeditview

blade
<p>
    @if ($operation === 'create')
        This is a new post.
    @else
        This is an existing post.
    @endif
</p>

在 Blade 视图中访问当前 Livewire 组件实例

在 Blade 视图中,可使用 $this 访问当前 Livewire 组件实例:

blade
@php
    use Filament\Resources\Users\RelationManagers\PostsRelationManager;
@endphp

<p>
    @if ($this instanceof PostsRelationManager)
        You are editing posts the of a user.
    @endif
</p>

在 Blade 视图中访问当前组件实例

在 Blade 视图中,可使用 $schemaComponent 访问当前组件实例。可在该对象上调用公共方法,以访问变量中可能不可用的其他信息:

blade
<p>
    @if ($schemaComponent->getState())
        This is a new post.
    @endif
</p>

向 schema 插入 Livewire 组件

可直接向 schema 插入 Livewire 组件:

php
use App\Livewire\Chart;
use Filament\Schemas\Components\Livewire;

Livewire::make(Chart::class)

INFO

向 schema 插入 Livewire 组件时能力有限。由于它们分开渲染,嵌套的 Livewire 组件只能访问可序列化数据。因此,你无法 渲染子 schema访问另一个组件的实时状态访问当前 Livewire 组件实例访问当前组件实例。只有 传给 Livewire 组件的静态数据 以及 当前记录 可访问。由于这些限制,应渲染嵌套 Livewire 组件而非 Blade 视图 的情况很少见。

若渲染多个相同的 Livewire 组件,请务必为每个传入唯一的 key()

php
use App\Livewire\Chart;
use Filament\Schemas\Components\Livewire;

Livewire::make(Chart::class)
    ->key('chart-first')

Livewire::make(Chart::class)
    ->key('chart-second')

Livewire::make(Chart::class)
    ->key('chart-third')

向 Livewire 组件传递参数

可向 Livewire 组件传入参数数组:

php
use App\Livewire\Chart;
use Filament\Schemas\Components\Livewire;

Livewire::make(Chart::class, ['bar' => 'baz'])

TIP

除了接受静态值外,make() 方法也接受函数以动态计算。你可以将各种工具作为参数注入该函数。

现在,这些参数会传给 Livewire 组件的 mount() 方法:

php
class Chart extends Component
{
    public function mount(string $bar): void
    {       
        // ...
    }
}

或者,它们也可作为 Livewire 组件上的公共属性使用:

php
class Chart extends Component
{
    public string $bar;
}

在 Livewire 组件中访问当前记录

可在 Livewire 组件中通过 mount() 方法的 $record 参数或 $record 属性访问当前记录:

php
use Illuminate\Database\Eloquent\Model;

class Chart extends Component
{
    public function mount(?Model $record = null): void
    {       
        // ...
    }
    
    // or
    
    public ?Model $record = null;
}

请注意,记录尚未创建时会为 null。若希望在记录为 null 时隐藏 Livewire 组件,可使用 hidden() 方法:

php
use Filament\Schemas\Components\Livewire;
use Illuminate\Database\Eloquent\Model;

Livewire::make(Chart::class)
    ->hidden(fn (?Model $record): bool => $record === null)

惰性加载 Livewire 组件

可使用 lazy() 方法允许组件 惰性加载

php
use Filament\Schemas\Components\Livewire;
use App\Livewire\Chart;

Livewire::make(Chart::class)
    ->lazy()

自定义组件类

你可以创建自己的自定义组件类与视图,在项目中复用,甚至作为插件发布给社区。

TIP

若只是创建一次性使用的简单自定义组件,也可改用 视图组件 渲染任意自定义 Blade 文件。

要创建自定义组件类与视图,可使用以下命令:

bash
php artisan make:filament-schema-component Chart

这将创建如下组件类:

php
use Filament\Schemas\Components\Component;

class Chart extends Component
{
    protected string $view = 'filament.schemas.components.chart';

    public static function make(): static
    {
        return app(static::class);
    }
}

同时会在 resources/views/filament/schemas/components/chart.blade.php 创建视图文件。

INFO

Filament schema 组件不是 Livewire 组件。在 schema 组件类上定义公共属性与方法,并不会使它们在 Blade 视图中可访问。

向自定义组件类添加配置方法

可向自定义组件类添加公共方法:接受配置值、存入受保护属性,再通过另一个公共方法返回:

php
use Filament\Schemas\Components\Component;

class Chart extends Component
{
    protected string $view = 'filament.schemas.components.chart';
    
    protected ?string $heading = null;

    public static function make(): static
    {
        return app(static::class);
    }

    public function heading(?string $heading): static
    {
        $this->heading = $heading;

        return $this;
    }

    public function getHeading(): ?string
    {
        return $this->heading;
    }
}

现在,在自定义组件的 Blade 视图中,可使用 $getHeading() 函数访问 heading:

blade
<div>
    {{ $getHeading() }}
</div>

你在自定义组件类上定义的任何公共方法,都可在 Blade 视图中以这种方式作为变量函数访问。

要将配置值传给自定义组件类,可使用该公共方法:

php
use App\Filament\Schemas\Components\Chart;

Chart::make()
    ->heading('Sales')

在自定义组件配置方法中允许工具注入

工具注入 是 Filament 的强大功能,允许用户使用可访问各种工具的函数来配置组件。可通过确保配置的参数类型与属性类型允许用户传入 Closure 来启用工具注入。在 getter 方法中,应将配置值传给 $this->evaluate() 方法:若用户传入函数则向其注入工具,若为静态值则直接返回:

php
use Closure;
use Filament\Schemas\Components\Component;

class Chart extends Component
{
    protected string $view = 'filament.schemas.components.chart';
    
    protected string | Closure | null $heading = null;

    public static function make(): static
    {
        return app(static::class);
    }

    public function heading(string | Closure | null $heading): static
    {
        $this->heading = $heading;

        return $this;
    }

    public function getHeading(): ?string
    {
        return $this->evaluate($this->heading);
    }
}

现在,可向 heading() 方法传入静态值或函数,并将 任意工具 作为参数注入:

php
use App\Filament\Schemas\Components\Chart;

Chart::make()
    ->heading(fn (Product $record): string => "{$record->name} Sales")

在自定义组件类构造函数中接受配置值

可在自定义组件的 make() 构造方法中接受配置值,并将其传给对应的 setter 方法:

php
use Closure;
use Filament\Schemas\Components\Component;

class Chart extends Component
{
    protected string $view = 'filament.schemas.components.chart';

    protected string | Closure | null $heading = null;

    public function __construct(string | Closure | null $heading = null)
    {
        $this->heading($heading)
    }

    public static function make(string | Closure | null $heading = null): static
    {
        return app(static::class, ['heading' => $heading]);
    }

    public function heading(string | Closure | null $heading): static
    {
        $this->heading = $heading;

        return $this;
    }

    public function getHeading(): ?string
    {
        return $this->evaluate($this->heading);
    }
}

从 JavaScript 调用组件方法

有时需要从 Blade 视图中的 JavaScript 调用组件类上的方法。例如,你可能想异步获取数据或执行一些服务端计算。Filament 提供了使用 #[ExposedLivewireMethod] 属性将组件类上的方法暴露给 JavaScript 的方式。

暴露方法

要将方法暴露给 JavaScript,请在自定义组件类的公共方法上添加 #[ExposedLivewireMethod] 属性:

php
use Filament\Schemas\Components\Component;
use Filament\Support\Components\Attributes\ExposedLivewireMethod;

class Chart extends Component
{
    protected string $view = 'filament.schemas.components.chart';

    public static function make(): static
    {
        return app(static::class);
    }

    #[ExposedLivewireMethod]
    public function getChartData(): array
    {
        // Fetch and process chart data...

        return $chartData;
    }
}

INFO

只有标记了 #[ExposedLivewireMethod] 的方法才能从 JavaScript 调用。这是防止任意方法执行的安全措施。

从 JavaScript 调用方法

在 Blade 视图中,可用 $wire.callSchemaComponentMethod() 调用已暴露的方法。第一个参数是组件的 key(可通过 $getKey() 获取),第二个是方法名,第三个参数可传入实参:

blade
@php
    $key = $getKey();
@endphp

    <template x-if="data">
        {{-- Render the chart using the data --}}
    </template>

可通过将对象作为第三个参数向方法传递实参:

blade
@php
    $key = $getKey();
@endphp

    <select x-model="dateRange" x-on:change="loadData">
        <option value="week">This Week</option>
        <option value="month">This Month</option>
        <option value="year">This Year</option>
    </select>

    <template x-if="data">
        {{-- Render the chart using the data --}}
    </template>

防止重新渲染

默认情况下,调用已暴露方法会触发 Livewire 组件重新渲染。若方法无需更新 UI,可在 #[ExposedLivewireMethod] 旁加上 Livewire 的 #[Renderless] 属性以跳过重新渲染:

php
use Filament\Schemas\Components\Component;
use Filament\Support\Components\Attributes\ExposedLivewireMethod;
use Livewire\Attributes\Renderless;

class Chart extends Component
{
    protected string $view = 'filament.schemas.components.chart';

    public static function make(): static
    {
        return app(static::class);
    }

    #[ExposedLivewireMethod]
    #[Renderless]
    public function getChartData(): array
    {
        // ...
    }
}