公告: 旧版文档请移步 -> http://v2.laravel-filament.cn/docs

Languages

Version

Theme

表单构造器

表单字段控件

开始

字段类(Field)位于 Filament\Form\Components 命名空间中。

字段组件和布局组件一起,在表单 schema 中。

如果你想在 Livewire 组件中使用这些字段,可以将它们放到 getFormSchema() 方法中:

protected function getFormSchema(): array
{
return [
// ...
];
}

如果你在后台面板的资源或者关联管理器中使用,必须将它们放在 $form->schema() 方法中:

public static function form(Form $form): Form
{
return $form
->schema([
// ...
]);
}

字段可以用静态方法 make() 传入字段名为参数创建。字段名应该对应 Livewire 组件的属性名。你可以使用 Livewire "点语法"将字段绑定到像数组或者 Eloquent 模型这样的嵌套属性中。

use Filament\Forms\Components\TextInput;
 
TextInput::make('name')

设置标签

默认情况下,字段标签会按照字段名自动生成。你可以使用 label() 方法重写字段标签。如果你想使用语言本地化,可以使用这种方法自定义标签:

use Filament\Forms\Components\TextInput;
 
TextInput::make('name')->label(__('fields.name'))

此外,你也可以使用 translateLabel() 方法自动翻译标签:

use Filament\Forms\Components\TextInput;
 
TextInput::make('name')->translateLabel() // 相当于 label(__('Name'))

设置 ID

像设置标签一样,字段ID会根据他们的字段名自动生成。可以使用 id() 重写:

use Filament\Forms\Components\TextInput;
 
TextInput::make('name')->id('name-field')

设置默认值

字段可以有默认值。如果表单 fill() 方法调用时没有传参,就会填充这个默认值。使用 default() 方法,可以定义默认值:

use Filament\Forms\Components\TextInput;
 
TextInput::make('name')->default('John')

帮助消息及提示

有时,你需要为表单用户提供额外消息。这种情况下,你可以使用帮助消息或者提示。

帮助消息显示在字段下面。helperText() 方法支持 Mardown 格式:

use Filament\Forms\Components\TextInput;
 
TextInput::make('name')->helperText('Your full name here, including any middle names.')

提示可以显示在标签旁边:

use Filament\Forms\Components\TextInput;
 
TextInput::make('password')->hint('[Forgotten your password?](forgotten-password)')

提示也可以添加图标,将其渲染在旁边:

use Filament\Forms\Components\RichEditor;
 
RichEditor::make('content')
->hint('Translatable')
->hintIcon('heroicon-s-translate')

提示也可以添加颜色 color()。默认是灰色,不过你也可以设为 primarysuccesswarningdanger

use Filament\Forms\Components\RichEditor;
 
RichEditor::make('content')
->hint('Translatable')
->hintColor('primary')

自定义属性

可以在 extraAttributes() 中传入一个数组,自定义字段所在代码块的 HTML 属性:

use Filament\Forms\Components\TextInput;
 
TextInput::make('name')->extraAttributes(['title' => 'Text input'])

如果要将额外的 HTML 属性添加到输入框本身,则使用 extraInputAttributes():

use Filament\Forms\Components\TextInput;
 
TextInput::make('categories')
->extraInputAttributes(['multiple' => true])

禁用

你可以禁用字段,使之不能编辑:

use Filament\Forms\Components\TextInput;
 
TextInput::make('name')->disabled()

另外,也可以传一个布尔值控制字段是否禁用:

use Filament\Forms\Components\Toggle;
 
Toggle::make('is_admin')->disabled(! auth()->user()->isAdmin())

请注意,禁用字段并不会影响保存,懂技术的用户仍然可以操作页面 HTML 改变他的值。

要阻止字段值被保存,请使用 dehydrated(false) 方法:

Toggle::make('is_admin')->dehydrated(false)

此外,你也可以根据情况决定是否保存一个字段,比如当用户是管理员时:

Toggle::make('is_admin')
->disabled(! auth()->user()->isAdmin())
->dehydrated(auth()->user()->isAdmin())

如果你使用后台面板,且只想在资源的新建页保存禁用字段:

use Filament\Resources\Pages\CreateRecord;
use Filament\Resources\Pages\Page;
 
TextInput::make('slug')
->disabled()
->dehydrated(fn (Page $livewire) => $livewire instanceof CreateRecord)

隐藏字段

你可以隐藏一个字段:

use Filament\Forms\Components\TextInput;
 
TextInput::make('name')->hidden()

另外,你也可以传入一个布尔值来控制字段是否隐藏:

use Filament\Forms\Components\TextInput;
 
TextInput::make('name')->hidden(! auth()->user()->isAdmin())

自动聚焦

大部分字段时可自动聚焦的。一般来说,让你表单中第一个重要的字段获得自动聚焦,会带来最好的用户体验。

use Filament\Forms\Components\TextInput;
 
TextInput::make('name')->autofocus()

设置占位符

很多字段当值为空时,通常会有一个占位符。你可以使用 placeholder() 方法自定义:

use Filament\Forms\Components\TextInput;
 
TextInput::make('name')->placeholder('John Doe')

全局设置

如果你想要全局修改字段的默认行为,你可以在服务提供者的 boot() 方法中调用静态方法 configrueUsing(),传入闭包修改其使用的组件。比如,你想让所有的复选框 inline(false),你可以这样做:

use Filament\Forms\Components\Checkbox;
 
Checkbox::configureUsing(function (Checkbox $checkbox): void {
$checkbox->inline(false);
});

当然,你仍然可以对每个字段单独重写这一样式:

use Filament\Forms\Components\Checkbox;
 
Checkbox::make('is_admin')->inline()

文本框

文本框(Text Input)用于与字符串交互:

use Filament\Forms\Components\TextInput;
 
TextInput::make('name')

你可以用一系列方法设置文本框类型。其中有些,比如像 email(),同时也提供验证:

use Filament\Forms\Components\TextInput;
 
TextInput::make('text')
->email()
->numeric()
->password()
->tel()
->url()

同样的,你也可以使用 type() 传入一个 HTML 文本框类型参数:

use Filament\Forms\Components\TextInput;
 
TextInput::make('backgroundColor')->type('color')

你可以设置 minLength()maxLength() 限制输入文本长度。此方法会同时添加前端和后端验证:

use Filament\Forms\Components\TextInput;
 
TextInput::make('name')
->minLength(2)
->maxLength(255)

你也可以通过设置 length() 指定输入框的精确长度。此方法同样在前后端都添加了验证:

use Filament\Forms\Components\TextInput;
 
TextInput::make('code')->length(8)

另外,你也可以设置 minValue()maxValue() 验证输入的最小和最大值:

use Filament\Forms\Components\TextInput;
 
TextInput::make('number')
->numeric()
->minValue(1)
->maxValue(100)

你可以使用 autocomplete() 方法,为文本输入框设置自动补全配置:

use Filament\Forms\Components\TextInput;
 
TextInput::make('password')
->password()
->autocomplete('new-password')

你也可以用 disableAutocomplete(),它是关闭自动补全的快捷方法:

use Filament\Forms\Components\TextInput;
 
TextInput::make('password')
->password()
->disableAutocomplete()

更多自动补全选项,文本框也支持 datalists

电话号码验证

使用 tel() 字段时,字段值将会使用如下规则进行验证:/^[+]*[(]{0,1}[0-9]{1,4}[)]{0,1}[-\s\.\/0-9]*$/

如果你需要修改验证规则,可以使用 telRegex() 方法:

use Filament\Forms\Components\TextInput;
 
TextInput::make('phone')
->tel()
->telRegex('/^[+]*[(]{0,1}[0-9]{1,4}[)]{0,1}[-\s\.\/0-9]*$/')

另外,要在全局中自定义 telRegex(),请使用服务提供者:

use Filament\Forms\Components\TextInput;
 
TextInput::configureUsing(function (TextInput $component): void {
$component->telRegex('/^[+]*[(]{0,1}[0-9]{1,4}[)]{0,1}[-\s\.\/0-9]*$/');
});

前后缀

你也可以使用 prefix()suffix() 方法,在文本框前后添加文本内容:

use Filament\Forms\Components\TextInput;
 
TextInput::make('domain')
->url()
->prefix('https://')
->suffix('.com')

你可以使用 prefixIcon()suffixIcon() 方法在输入框前后放入图标:

use Filament\Forms\Components\TextInput;
 
TextInput::make('domain')
->url()
->prefixIcon('heroicon-o-external-link')
->suffixIcon('heroicon-o-external-link')

你也可以使用 prefixAction()suffixAction() 方法,在输入框前后渲染 Action 按钮:

use Filament\Forms\Components\Actions\Action;
use Filament\Forms\Components\TextInput;
 
TextInput::make('domain')
->suffixAction(fn (?string $state): Action =>
Action::make('visit')
->icon('heroicon-s-external-link')
->url(
filled($state) ? "https://{$state}" : null,
shouldOpenInNewTab: true,
),
)

输入遮罩

输入遮罩(Input mask)定义了输入必须遵循的格式。

Filament 中,你可以在 mask() 方法中与 Mask 对象进行交互,配置你的 mask:

use Filament\Forms\Components\TextInput;
 
TextInput::make('name')
->mask(fn (TextInput\Mask $mask) => $mask->pattern('+{7}(000)000-00-00'))

在底层,masking 使用 imaskjs 驱动。它主要的特性在 Filament 中同样可用。先阅读指南,再使用 Filament 实现,或许是最便利的方法。

你可以定义和配置一个 numeric mask,用来处理数字:

use Filament\Forms\Components\TextInput;
 
TextInput::make('number')
->numeric()
->mask(fn (TextInput\Mask $mask) => $mask
->numeric()
->decimalPlaces(2) // Set the number of digits after the decimal point.
->decimalSeparator(',') // Add a separator for decimal numbers.
->integer() // Disallow decimal numbers.
->mapToDecimalSeparator([',']) // Map additional characters to the decimal separator.
->minValue(1) // Set the minimum value that the number can be.
->maxValue(100) // Set the maximum value that the number can be.
->normalizeZeros() // Append or remove zeros at the end of the number.
->padFractionalZeros() // Pad zeros at the end of the number to always maintain the maximum number of decimal places.
->thousandsSeparator(','), // Add a separator for thousands.
)

Enum masks 可以限制用户的输入选项:

use Filament\Forms\Components\TextInput;
 
TextInput::make('code')->mask(fn (TextInput\Mask $mask) => $mask->enum(['F1', 'G2', 'H3']))

Range masks 可被用作限制数字输入范围:

use Filament\Forms\Components\TextInput;
 
TextInput::make('code')->mask(fn (TextInput\Mask $mask) => $mask
->range()
->from(1) // Set the lower limit.
->to(100) // Set the upper limit.
->maxValue(100), // Pad zeros at the start of smaller numbers.
)

除了简单样式,你也可以定义多重模式块 pattern blocks:

use Filament\Forms\Components\TextInput;
 
TextInput::make('cost')->mask(fn (TextInput\Mask $mask) => $mask
->patternBlocks([
'money' => fn (Mask $mask) => $mask
->numeric()
->thousandsSeparator(',')
->decimalSeparator('.'),
])
->pattern('$money'),
)

里面也包含了一个 money() 方法,可以更容易格式化货币输入。本例,前缀符号是 $、千位分隔符 , 及两位小数:

use Filament\Forms\Components\TextInput;
 
TextInput::make('cost')->mask(fn (TextInput\Mask $mask) => $mask->money(prefix: '$', thousandsSeparator: ',', decimalPlaces: 2))

Datalist 为用户提供文本框自动补全选项。不过,这些值只是单纯推荐,用户仍然可以输入任何值到文本框中。如果你想要限制定义选项,请用选择框

下拉列表

下拉列表组件让你可以使用一组预定义的选项:

use Filament\Forms\Components\Select;
 
Select::make('status')
->options([
'draft' => 'Draft',
'reviewing' => 'Reviewing',
'published' => 'Published',
])

在选项中的数组,数组的键名会被保存,数组值则是每个下拉选项的标签。

你可以使用 searchable() 方法启用搜索输入框,使之更容易找到选项:

use Filament\Forms\Components\Select;
 
Select::make('authorId')
->label('Author')
->options(User::all()->pluck('name', 'id'))
->searchable()

如果你有很多选项,需要根据数据库搜索或者其他外部数据源填充数据,你可以使用 getSearchResultsUsing()getOptionLabelUsing() 方法代替 options()

getSearchResultsUsing() 方法接收一个回调函数作为参数,该回调以 $key => $value 格式返回搜索结果。

getSearchResultsUsing() 方法接收一个回调函数,该回调将选中的选项的 $value 转换成标签。

Select::make('authorId')
->searchable()
->getSearchResultsUsing(fn (string $searchQuery) => User::where('name', 'like', "%{$searchQuery}%")->limit(50)->pluck('name', 'id'))
->getOptionLabelUsing(fn ($value): ?string => User::find($value)?->name),

使用 disablePlaceholderSelection() 方法可以防止占位符被选中:

use Filament\Forms\Components\Select;
 
Select::make('status')
->options([
'draft' => 'Draft',
'reviewing' => 'Reviewing',
'published' => 'Published',
])
->default('draft')
->disablePlaceholderSelection()

Multi-select

Select 组件上使用 multiple() 方法,允许你在下拉列表中进行多选:

use Filament\Forms\Components\Select;
 
Select::make('technologies')
->multiple()
->options([
'tailwind' => 'Tailwind CSS',
'alpine' => 'Alpine.js',
'laravel' => 'Laravel',
'livewire' => 'Laravel Livewire',
])

这些选项以 JSON 格式返回。如果你使用的是 Eloquent,你应该在模型属性中添加 array casts

use Illuminate\Database\Eloquent\Model;
 
class App extends Model
{
protected $casts = [
'technologies' => 'array',
];
 
// ...
}

getOptionLabelsUsing() 方法可以用作对选中的选项值转成标签。注意,getOptionLabelUsing() 将被 getOptionLabelsUsing() 替换。

依赖下拉列表

通常情况下,你可能会需要用到"依赖"下拉列表,它基于其他字段控件的状态值填充选项。

高级表单区域提及的一些技术,需要使用依赖下拉列表。可使用这些技术对所有表单组件进行动态自定义。

从关联中自动加载数据

你可以使用 Selectrelationship() 方法,用以配置 BelongTo 关联模型,自动检索和保存选项:

use Filament\Forms\Components\Select;
 
Select::make('authorId')
->relationship('author', 'name')

multiple() 方法可与 relationship() 方法联合使用,用来从 BelongsToMany 关联中自动加载数据:

use Filament\Forms\Components\Select;
 
Select::make('technologies')
->multiple()
->relationship('technologies', 'name')

要启用这个功能,你必须按照关联字段区域的指南进行设置。如果你使用了后台面板,可以跳过此步。

你可以使用 relationship() 方法的第三个参数,自定义数据库查询:

use Filament\Forms\Components\Select;
 
Select::make('authorId')
->relationship('author', 'name')
->preload()

你可以使用 relationship() 方法的第三个参数来自定义数据库查询检索选项:

use Filament\Forms\Components\Select;
use Illuminate\Database\Eloquent\Builder;
 
Select::make('authorId')
->relationship('author', 'name', fn (Builder $query) => $query->withTrashed())

如果你想要自定义每个选项的标签,比如让其更具描述性、或者连接名和姓,你应该在数据库迁移中使用(virtual)虚拟字段:

$table->string('full_name')->virtualAs('concat(first_name, \' \', last_name)');
use Filament\Forms\Components\Select;
 
Select::make('authorId')
->relationship('author', 'full_name')

另外,你也可以使用 getOptionLabelFromRecordUsing() 方法将选中选项的 Eloquent 模型转换成标签。不过需要注意的是,这种方式比使用虚拟字段(virtual column)低效:

use Filament\Forms\Components\Select;
use Illuminate\Database\Eloquent\Model;
 
Select::make('authorId')
->relationship('author', 'first_name')
->getOptionLabelFromRecordUsing(fn (Model $record) => "{$record->first_name} {$record->last_name}")

处理 MorphTo 关联

MorphTo 关联比较特别,因为它使用户可以从一系列不同模型中选则记录。因此,有了 MorphToSelect 组件,实际上它不是一个 Select 字段,而是 Fieldset 中的两个 Select 字段。第一个 Select 字段允许你选择类型,第二个允许你选择对应类型的记录。

要使用 MorphToSelect,你必须将类型通过 types() 传入组件,使组件了解如何渲染不同类型选项:

use Filament\Forms\Components\MorphToSelect;
 
MorphToSelect::make('commentable')
->types([
MorphToSelect\Type::make(Product::class)->titleColumnName('name'),
MorphToSelect\Type::make(Post::class)->titleColumnName('title'),
])

titleColumnName() 被用作从 Product 或者 Post 中提取出标题。你也可以使用 getOptionLabelFromRecordUsing() 提取选项标签:

use Filament\Forms\Components\MorphToSelect;
 
MorphToSelect::make('commentable')
->types([
MorphToSelect\Type::make(Product::class)
->getOptionLabelFromRecordUsing(fn (Product $record): string => "{$record->name} - {$record->slug}"),
MorphToSelect\Type::make(Post::class)->titleColumnName('title'),
])

你也可以使用 modifyOptionsQueryUsing() 方法自定义数据查询检索选项:

use Filament\Forms\Components\MorphToSelect;
use Illuminate\Database\Eloquent\Builder;
 
MorphToSelect::make('commentable')
->types([
MorphToSelect\Type::make(Product::class)
->titleColumnName('name')
->modifyOptionsQueryUsing(fn (Builder $query) => $query->whereBelongsTo($this->team)),
MorphToSelect\Type::make(Post::class)
->titleColumnName('title')
->modifyOptionsQueryUsing(fn (Builder $query) => $query->whereBelongsTo($this->team)),
])

在 Select 字段中许多选项对于 MorphToSelect 都是可用的,包括 searchable()preload()allowHtml()optionsLimit()

创建新记录

你可以自定义表单,使之可以用来创建新纪录并附加到 BelongsTo 关联:

use Filament\Forms\Components\Select;
use Illuminate\Database\Eloquent\Model;
 
Select::make('authorId')
->relationship('author', 'name')
->createOptionForm([
Forms\Components\TextInput::make('name')
->required(),
Forms\Components\TextInput::make('email')
->required()
->email(),
]),

这个表单会在模态框内打开,用户可以在里面填写数据。一旦表单提交,新记录就会被字段选中。

由于 HTML 不支持嵌套 <form> 元素,你必须在视图的 <form> 表单之外渲染模态框。如果你使用后台面板,这已经被包含在内了:

<form wire:submit.prevent="submit">
{{ $this->form }}
<button type="submit">
Submit
</button>
</form>
 
{{ $this->modal }}

复选框

复选框(checkbox)组件,类似于 toggle,让你可以和布尔值交互。

use Filament\Forms\Components\Checkbox;
 
Checkbox::make('is_admin')

复选框字段有两种布局模式,inline 和 stacked。默认为 inline。

如果是 inline,标签会紧邻着复选框:

use Filament\Forms\Components\Checkbox;
 
Checkbox::make('is_admin')->inline()

如果是 stacked,标签会在复选框之上:

use Filament\Forms\Components\Checkbox;
 
Checkbox::make('is_admin')->inline(false)

如果你使用 Eloquent 保存布尔值,你应该添加 boolean casts 到模型属性中:

use Illuminate\Database\Eloquent\Model;
 
class User extends Model
{
protected $casts = [
'is_admin' => 'boolean',
];
 
// ...
}

Toggle

Toggle 组件,类似于 复选框,用于和布尔值交互。

use Filament\Forms\Components\Toggle;
 
Toggle::make('is_admin')

Toggle 字段控件有两种布局模式,inline 和 stacked。默认是 inline(行内)。

如果是 inline,标签会紧挨着它:

use Filament\Forms\Components\Toggle;
 
Toggle::make('is_admin')->inline()

如果是 stacked,标签会在它上面:

use Filament\Forms\Components\Toggle;
 
Toggle::make('is_admin')->inline(false)

Toggle 也可以使用开/关图标。会被显示在手柄上,指示字段含义。参数必须是 Blade 模板图标组件:

use Filament\Forms\Components\Toggle;
 
Toggle::make('is_admin')
->onIcon('heroicon-s-lightning-bolt')
->offIcon('heroicon-s-user')

你也可以自定义每个状态显示的颜色。可用颜色包括 primarysecondarysuccesswarningdanger

use Filament\Forms\Components\Toggle;
 
Toggle::make('is_admin')
->onColor('success')
->offColor('danger')

如果你使用 Eloquent 保存布尔值,你应该添加 boolean casts 到相应的模型属性上。

use Illuminate\Database\Eloquent\Model;
 
class User extends Model
{
protected $casts = [
'is_admin' => 'boolean',
];
 
// ...
}

复选框列表

复选框列表让你可以从一组预定义的选项中选择多个值:

use Filament\Forms\Components\CheckboxList;
 
CheckboxList::make('technologies')
->options([
'tailwind' => 'TailwindCSS',
'alpine' => 'Alpine.js',
'laravel' => 'Laravel',
'livewire' => 'Laravel Livewire',
])

这些选项以 JSON 格式返回。如果你使用 Eloquent 保存数据,你应该添加 array casts 到模型属性中:

use Illuminate\Database\Eloquent\Model;
 
class App extends Model
{
protected $casts = [
'technologies' => 'array',
];
 
// ...
}

你也可以使用 columns() 方法将选项分成对应的列数:

use Filament\Forms\Components\CheckboxList;
 
CheckboxList::make('technologies')
->options([
'tailwind' => 'TailwindCSS',
'alpine' => 'Alpine.js',
'laravel' => 'Laravel',
'livewire' => 'Laravel Livewire',
])
->columns(2)

此方法像 gridcolumns() 方法一样,接收选项作为参数。你可以在不同的临界点中,以自适应的方式定制列数。

你也可以使用 bulkToggleable() 方法让用户一次性切换所有复选框:

use Filament\Forms\Components\CheckboxList;
 
CheckboxList::make('technologies')
->options([
'tailwind' => 'Tailwind CSS',
'alpine' => 'Alpine.js',
'laravel' => 'Laravel',
'livewire' => 'Laravel Livewire',
])
->bulkToggleable()

自动从关联中获取数据

你可以使用 relationship() 方法,配置关联模型用来自动检索和保存选项:

use Filament\Forms\Components\CheckboxList;
 
CheckboxList::make('technologies')
->relationship('technologies', 'name')

要启用这个功能,你必须按照关联字段区域的指南进行设置。如果你使用了后台面板,可以跳过此步。

你可以使用 relationship() 方法的第三个参数,自定义数据库查询检索选项:

use Filament\Forms\Components\CheckboxList;
use Illuminate\Database\Eloquent\Builder;
 
CheckboxList::make('technologies')
->relationship('technologies', 'name', fn (Builder $query) => $query->withTrashed())

如果你想要自定义每个选项的标签,比如让它更具描述性、或者连接名和姓,你应该在数据库迁移中使用(virtual)虚拟字段:

$table->string('full_name')->virtualAs('concat(first_name, \' \', last_name)');
use Filament\Forms\Components\CheckboxList;
 
CheckboxList::make('participants')
->relationship('participants', 'full_name')

另外,你也可以使用 getOptionLabelFromRecordUsing() 方法将选中选项的 Eloquent 模型转换成标签。不过需要注意的是,这种方式会比使用虚拟字段(virtual column)性能低:

use Filament\Forms\Components\CheckboxList;
use Illuminate\Database\Eloquent\Model;
 
CheckboxList::make('participants')
->relationship('participants', 'first_name')
->getOptionLabelFromRecordUsing(fn (Model $record) => "{$record->first_name} {$record->last_name}")

单选框

单选框提供单选按钮组,用来从一个预定义的选项列表中选择一个值:

use Filament\Forms\Components\Radio;
 
Radio::make('status')
->options([
'draft' => 'Draft',
'scheduled' => 'Scheduled',
'published' => 'Published'
])

你可以使用 descriptions() 方法提供对每个选项的描述:

use Filament\Forms\Components\Radio;
 
Radio::make('status')
->options([
'draft' => 'Draft',
'scheduled' => 'Scheduled',
'published' => 'Published'
])
->descriptions([
'draft' => 'Is not visible.',
'scheduled' => 'Will be visible.',
'published' => 'Is visible.'
])

请确保在描述数组中使用和选项数组中同样的 键(key),这样描述才能和选项匹配。

如果你只是需要简单的布尔单选按钮组,带有"是/否"选项,你可以使用 boolean() 方法:

Radio::make('feedback')
->label('Do you like this post?')
->boolean()

你可以使用标签在行内(inline)显示选项:

Radio::make('feedback')
->label('Do you like this post?')
->boolean()
->inline()

日期时间选择器

日期时间选择器(Date-time Picker)提供了选择日期和时间的交互接口。

use Filament\Forms\Components\DatePicker;
use Filament\Forms\Components\DateTimePicker;
use Filament\Forms\Components\TimePicker;
 
DateTimePicker::make('published_at')
DatePicker::make('date_of_birth')
TimePicker::make('alarm_at')

你可以限制选择器可选的最小/最大日期。minDate()maxDate() 方法接收一个 DateTime 实例(如 Carbon)或字符串作为参数:

use Filament\Forms\Components\DatePicker;
 
DatePicker::make('date_of_birth')
->minDate(now()->subYears(150))
->maxDate(now())

你可以使用 format() 方法,自定义存入数据库时的字段格式。它接收字符串日期格式,使用 PHP 日期格式

use Filament\Forms\Components\DatePicker;
 
DatePicker::make('date_of_birth')->format('d/m/Y')

你可以自定义字段的显示格式,以不同于存入数据库时候的格式。对此,使用 displayFormat() 方法,它也可以接收字符串日期格式,使用 PHP 日期格式:

use Filament\Forms\Components\DatePicker;
 
DatePicker::make('date_of_birth')->displayFormat('d/m/Y')

当使用的是时间选择器时,你可以使用 withoutSeconds() 方法禁用秒输入框:

use Filament\Forms\Components\DateTimePicker;
 
DateTimePicker::make('published_at')->withoutSeconds()

你也可以使用 hoursStep()minutesStep()secondsStep() 方法,自定义输入小时/分钟/秒钟的增加间隔:

use Filament\Forms\Components\DateTimePicker;
 
DateTimePicker::make('published_at')
->hoursStep(2)
->minutesStep(15)
->secondsStep(10)

在某些国家,星期的第一天不是周一。使用 forms.components.date_time_picker.first_day_of_week 配置选项或者组件的 firstDayOfWeek() 方法,可以自定义时间选择器中星期的第一天。可接收的参数值从 0 到 7,周一是1,周日为 7 或 0:

use Filament\Forms\Components\DateTimePicker;
 
DateTimePicker::make('published_at')->firstDayOfWeek(7)

另外也有一些额外的便利方法,可以更方便地设置星期的第一天:

use Filament\Forms\Components\DateTimePicker;
 
DateTimePicker::make('published_at')->weekStartsOnMonday()
DateTimePicker::make('published_at')->weekStartsOnSunday()

要禁用特定的日期:

use Filament\Forms\Components\DateTimePicker;
 
DateTimePicker::make('date')
->label('Appointment date')
->minDate(now())
->maxDate(Carbon::now()->addDays(30))
->disabledDates(['2022-10-02', '2022-10-05', '2022-10-15'])

你可以使用 icon 方法修改日历图标:

use Filament\Forms\Components\DateTimePicker;
 
DateTimePicker::make('date')
->icon('heroicon-o-calendar')

此外,你也可以传入 false 移除图标:

use Filament\Forms\Components\DateTimePicker;
 
DateTimePicker::make('date')
->icon(false)

时区

你可以使用 timezone() 方法,让用户可以管理自己的时区:

use Filament\Forms\Components\DateTimePicker;
 
DateTimePicker::make('published_at')->timezone('America/New_York')

日期仍然会使用应用配置的时区保存,日期在加载时会适用新的时区,表单保存时会转换回系统配置的时区。

文件上传

文件上传字段基于 Filepond

use Filament\Forms\Components\FileUpload;
 
FileUpload::make('attachment')

默认情况下,文件会被公开上传到默认的存储盘中。

请注意,要正确地预览图片及其他文件,FilePond 要求从与应相同的域名提供文件,否则需要设置设置好 CORS 标头。请确保 APP_URL 环境变量设置正确,或者修改文件系统驱动,以设置正确的 URL。如果你将文件托管在其他域名中,比如 S3,请确保 CORS 表头设置正确。

可以使用 disk()directory()visibility() 方法,修改文件保存的磁盘和目录,以及可见性:

use Filament\Forms\Components\FileUpload;
 
FileUpload::make('attachment')
->disk('s3')
->directory('form-attachments')
->visibility('private')

请注意,由开发者决定是否将文件从磁盘上删除,因为 Filament 不知道其他地方是否也依赖于他。一种自动实现的方法是监听模型事件

默认情况下,新上传的文件会生成随机文件名。可以使用 preserveFilenames() 方法,保留上传文件的原文件名:

use Filament\Forms\Components\FileUpload;
 
FileUpload::make('attachment')->preserveFilenames()

你可以使用 getUploadedFileNameForStorageUsing() 方法,在回调函数中返回字符串,这样就可以完全自定义文件名怎么生成:

use Livewire\TemporaryUploadedFile;
 
FileUpload::make('attachment')
->getUploadedFileNameForStorageUsing(function (TemporaryUploadedFile $file): string {
return (string) str($file->getClientOriginalName())->prepend('custom-prefix-');
})

使用 storeFileNamesIn() 方法,你可以在保留原始文件名的同时,使用随机生成的文件名:

use Filament\Forms\Components\FileUpload;
 
FileUpload::make('attachments')
->multiple()
->storeFileNamesIn('attachment_file_names')

attachment_file_names 中会保存你上传文件的原始文件名。

你可以使用 acceptedFileTypes() 方法,传入 MIME 类型数组,来限制可以上传的文件类型。你也可以使用 image() 方法作为速记方法,允许所有图片的 MIME 类型。

use Filament\Forms\Components\FileUpload;
 
FileUpload::make('document')->acceptedFileTypes(['application/pdf'])
FileUpload::make('image')->image()

你也可以限制上传文件的大小,以 KB 计算:

use Filament\Forms\Components\FileUpload;
 
FileUpload::make('attachment')
->minSize(512)
->maxSize(1024)

要自定义 Livewire 默认的文件上传验证规则,包括最大 12MB 文件限制,请查阅相关文档

Filepond 允许你在上传之前对图片进行裁切或者调整大小。你可以使用 imageResizeMode()imageCropAspectRatio()imageResizeTargetHeight()imageResizeTargetWidth() 方法进行自定义。其他方法要生效,需先设置 imageResizeMode() - 将其设为 forcecovercontain

use Filament\Forms\Components\FileUpload;
 
FileUpload::make('image')
->image()
->imageResizeMode('cover')
->imageCropAspectRatio('16:9')
->imageResizeTargetWidth('1920')
->imageResizeTargetHeight('1080')

你也可以修改 Filepond 组件的一般外观。这些方法可用的选项可以在 Filepond 网站查看。

use Filament\Forms\Components\FileUpload;
 
FileUpload::make('attachment')
->imagePreviewHeight('250')
->loadingIndicatorPosition('left')
->panelAspectRatio('2:1')
->panelLayout('integrated')
->removeUploadedFileButtonPosition('right')
->uploadButtonPosition('left')
->uploadProgressIndicatorPosition('left')

你也可以上传多个文件。网址会以 JSON 方式保存:

use Filament\Forms\Components\FileUpload;
 
FileUpload::make('attachments')->multiple()

如果你使用 Eloquent 保存这些网址,你需要添加 array casts 到模型属性中:

use Illuminate\Database\Eloquent\Model;
 
class Message extends Model
{
protected $casts = [
'attachments' => 'array',
];
 
// ...
}

使用 minFiles()maxFiles() 方法,你可以自定义文件上传的数量:

use Filament\Forms\Components\FileUpload;
 
FileUpload::make('attachments')
->multiple()
->minFiles(2)
->maxFiles(5)

使用 enableReordering() 方法,你也可以启用上传文件的重新排序功能:

use Filament\Forms\Components\FileUpload;
 
FileUpload::make('attachments')
->multipe()
->enableReordering()

使用 enableOpen() 方法,你可以添加按钮使文件可以在新的标签页中打开:

use Filament\Forms\Components\FileUpload;
 
FileUpload::make('attachments')
->multipe()
->enableOpen()

使用 enableDownload() 方法,你可以为每个上传文件添加一个下载按钮:

use Filament\Forms\Components\FileUpload;
 
FileUpload::make('attachments')
->multipe()
->enableDownload()

Filament 也支持 spatie/laravel-medialibrary。更多信息可查看插件文档

富文本编辑器

富文本编辑器让你可以编辑和预览 HTML 内容,上传图片。

use Filament\Forms\Components\RichEditor;
 
RichEditor::make('content')

你可以使用一系列便捷方法启用/禁用工具栏按钮:

use Filament\Forms\Components\RichEditor;
 
RichEditor::make('content')
->toolbarButtons([
'attachFiles',
'blockquote',
'bold',
'bulletList',
'codeBlock',
'h2',
'h3',
'italic',
'link',
'orderedList',
'redo',
'strike',
'undo',
])
RichEditor::make('content')
->disableToolbarButtons([
'attachFiles',
'codeBlock',
])
RichEditor::make('content')
->disableAllToolbarButtons()
->enableToolbarButtons([
'bold',
'bulletList',
'italic',
'strike',
])

你可以使用配置方法自定义图片如何上传:

use Filament\Forms\Components\RichEditor;
 
RichEditor::make('content')
->fileAttachmentsDisk('s3')
->fileAttachmentsDirectory('attachments')
->fileAttachmentsVisibility('private')

Markdown 编辑器

Markdown 编辑器让你可以编辑和预览 markdown 内容,也可以上传图片。

use Filament\Forms\Components\MarkdownEditor;
 
MarkdownEditor::make('content')

你可以使用一系列便捷方法启用/禁用工具栏按钮:

use Filament\Forms\Components\MarkdownEditor;
 
MarkdownEditor::make('content')
->toolbarButtons([
'attachFiles',
'bold',
'bulletList',
'codeBlock',
'edit',
'italic',
'link',
'orderedList',
'preview',
'strike',
])
MarkdownEditor::make('content')
->disableToolbarButtons([
'attachFiles',
'codeBlock',
])
MarkdownEditor::make('content')
->disableAllToolbarButtons()
->enableToolbarButtons([
'bold',
'bulletList',
'edit',
'italic',
'preview',
'strike',
])

你可以使用配置方法自定义图片如何上传:

use Filament\Forms\Components\MarkdownEditor;
 
MarkdownEditor::make('content')
->fileAttachmentsDisk('s3')
->fileAttachmentsDirectory('attachments')
->fileAttachmentsVisibility('private')

Hidden

Hidden 组件让你可以在表单内创建一个带值的隐藏(hidden)字段。

use Filament\Forms\Components\Hidden;
 
Hidden::make('token')

Repeater

Repeater 组件让你在重复的表单组件中输出 JSON 数组。

use Filament\Forms\Components\Repeater;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
 
Repeater::make('members')
->schema([
TextInput::make('name')->required(),
Select::make('role')
->options([
'member' => 'Member',
'administrator' => 'Administrator',
'owner' => 'Owner',
])
->required(),
])
->columns(2)

我们建议将数据以 JSON 字段的形式保存在数据库中。另外,如果使用了 Eloquent,确保对该字段进行了 array 强制转换(casts)。

如上例所示,组件的 schema 可以在 schema() 方法中定义:

use Filament\Forms\Components\Repeater;
use Filament\Forms\Components\TextInput;
 
Repeater::make('members')
->schema([
TextInput::make('name')->required(),
// ...
])

如果你想要使用多重 schema 代码块定义 Repeater 并使之可以以任何顺序重复,请使用 builer

使用 defaultItems() 方法,Repeater 默认会有一些特定数量的空项目。

use Filament\Forms\Components\Repeater;
 
Repeater::make('members')
->schema([
// ...
])
->defaultItems(3)

你可以设置标签,自定义显示在添加项目按钮上的文本。

use Filament\Forms\Components\Repeater;
 
Repeater::make('members')
->schema([
// ...
])
->createItemButtonLabel('Add member')

你也可以阻止用户添加项目,删除项目或者在 Repeater 内移动项目:

use Filament\Forms\Components\Repeater;
 
Repeater::make('members')
->schema([
// ...
])
->disableItemCreation()
->disableItemDeletion()
->disableItemMovement()

你可以使用 minItems()maxItems() 方法自定义创建的 Item 数量:

use Filament\Forms\Components\Repeater;
 
Repeater::make('members')
->schema([
// ...
])
->minItems(1)
->maxItems(10)

可折叠

Repeater 可以是可折叠的 collapsible(), 用来在长表单中选择性隐藏内容:

use Filament\Forms\Components\Repeater;
 
Repeater::make('qualifications')
->schema([
// ...
])
->collapsible()

你也可以让它在默认情况下是折叠的:

use Filament\Forms\Components\Repeater;
 
Repeater::make('qualifications')
->schema([
// ...
])
->collapsed()

克隆项目

使用 cloneable() 方法,可以允许复制 repeater 项:

use Filament\Forms\Components\Repeater;
 
Repeater::make('qualifications')
->schema([
// ...
])
->cloneable()

自动从关联中填充数据

你可以使用 Repeater 的 relationship() 方法配置关联,自动检索和保存 Repeater 数据:

use Filament\Forms\Components\Repeater;
 
Repeater::make('qualifications')
->relationship()
->schema([
// ...
])

要启用该功能,你也必须按照关联字段区域的指示进行设置。如果你使用后台面板,可以忽略此步

排序项目

默认情况下,对 Repeater 项目进行排序是被禁用的。这是因为关联模型需要有一个 sort 字段,用来保存关联记录的顺序。要启用排序,你可以使用 orderable() 方法:

use Filament\Forms\Components\Repeater;
 
HasManyRepeater::make('qualifications')
->relationship('qualifications')
->schema([
// ...
])
->orderable()

本例假定你的关联模型中有一个 sort 字段。

如果你使用了像 spatie/eloquent-sortable 这样的包,使用了像 order_column 这样的字段名作为排序字段,你可以将其作为参数传入 orderable() 中:

use Filament\Forms\Components\Repeater;
 
Repeater::make('qualifications')
->relationship('qualifications')
->schema([
// ...
])
->orderable('order_column')

网格布局

你可以使用 grid() 方法组织 Repeater 项目:

use Filament\Forms\Components\Repeater;
 
Repeater::make('members')
->schema([
// ...
])
->grid(2)

该方法与 gridcolumns() 方法相似,接收相同的参数选项。让你可以在不同临界点自定义网格列数。

项目标签

你可以使用 itemLabel() 方法,为 Repeater 项目添加标签:

use Filament\Forms\Components\Repeater;
use Filament\Forms\Components\TextInput;
 
Repeater::make('members')
->schema([
TextInput::make('name')
->lazy(),
])
->itemLabel(fn (array $state): ?string => $state['name'] ?? null),

如果你希望项目标签动态更新,那么使用 $state 获取的字段,应该是 reactive()lazy() 的。

使用 $get() 访问父级字段值

所有表单组件都可以使用 $get()$set() 获取其他字段的值。然而,在 Repeater 中使用可能会碰到异常。

这是因为默认情况下,$get()$set() 被限定在当前 repeater 项目中。也就是说,你可以在 repeater 项目中的其他字段交互,而不需要了解该表单属于哪一个 repeater 条目。

其结果是,当你不能与 repeater 字段进行互动时,会感到困惑。我们使用 ../ 语法来解决此问题 - $get('../../parent_field_name')

假设你的表单数据结构如下:

[
'client_id' => 1,
 
'repeater' => [
'item1' => [
'service_id' => 2,
],
],
]

你需要在 repeater 项目中检索 client_id 的值。

$get() 用于检索当前的 repeater 项, 因此 $get('client_id') 意味着 $get('repeater.item1.client_id')

你可以使用 ../ 切换到数据结构的上一级,因此 $get('../client_id') 相当于 $get('repeater.client_id')$get('../../client_id') 相当于 $get('client_id')

Builder

类似于 Repeater,Builder 组件让你可以以 JSON 数组的形式输出重复的表单组件。所有不同的是,Repeater 只定义了一个需要重复的表单的 schema,而 Builder 允许定义多个 schema 代码块,你可以以任何顺序进行排序。这有助于创建更高级的数组结构。

Builder 组件的主要用途,是使用预定义的代码块来搭建网页内容。下例在页面内容中为不同的元素定义了多个代码块。在你网站的前端,你可以使用 JSON 或者你需要的格式遍历每个代码块。

use Filament\Forms\Components\Builder;
use Filament\Forms\Components\FileUpload;
use Filament\Forms\Components\MarkdownEditor;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
 
Builder::make('content')
->blocks([
Builder\Block::make('heading')
->schema([
TextInput::make('content')
->label('Heading')
->required(),
Select::make('level')
->options([
'h1' => 'Heading 1',
'h2' => 'Heading 2',
'h3' => 'Heading 3',
'h4' => 'Heading 4',
'h5' => 'Heading 5',
'h6' => 'Heading 6',
])
->required(),
]),
Builder\Block::make('paragraph')
->schema([
MarkdownEditor::make('content')
->label('Paragraph')
->required(),
]),
Builder\Block::make('image')
->schema([
FileUpload::make('url')
->label('Image')
->image()
->required(),
TextInput::make('alt')
->label('Alt text')
->required(),
]),
])

建议在数据库中以 JSON 方式保存 Builder 的数据。另外,如果使用的是 Eloquent,确保对字段进行 array 造型。

如上例所示,代码块被定义在组件的 blocks() 方法中。代码块(Block) 是 Builder\Block 对象,有一个唯一名称以及一个组件 schema:

use Filament\Forms\Components\Builder;
use Filament\Forms\Components\TextInput;
 
Builder::make('content')
->blocks([
Builder\Block::make('heading')
->schema([
TextInput::make('content')->required(),
// ...
]),
// ...
])

默认情况下,代码块的标签会基于其名称自动生成。要重写代码块标签,请使用 label() 方法。如果你想使用本地化翻译字符,以此自定义标签是个有效的方式:

use Filament\Forms\Components\Builder;
 
Builder\Block::make('heading')->label(__('blocks.heading'))

Block 也可以添加图标,显示在标签旁边。icon() 方法接收 Blade 图标组件作为参数:

use Filament\Forms\Components\Builder;
 
Builder\Block::make('heading')->icon('heroicon-o-bookmark')

你也可以使用 minItems()maxItems() 方法自定义可以创建的项目数量:

use Filament\Forms\Components\Builder;
use Filament\Forms\Components\TextInput;
 
Builder::make('content')
->blocks([
// ...
])
->minItems(1)
->maxItems(10)

可折叠

可以使用 collapsible() 方法,在长表单中选择性隐藏内容:

use Filament\Forms\Components\Builder;
 
Builder::make('content')
->blocks([
// ...
])
->collapsible()

可以默认折叠所有项目:

use Filament\Forms\Components\Builder;
 
Builder::make('content')
->blocks([
// ...
])
->collapsed()

标签输入框

标签(Tag)输入组件让你可以和标签列表交互。

默认情况下,标签以 JOSN 方式保存:

use Filament\Forms\Components\TagsInput;
 
TagsInput::make('tags')

如果你使用 Eloquent 保存 JSON 标签,你应该在模型属性中添加 array casts

use Illuminate\Database\Eloquent\Model;
 
class Post extends Model
{
protected $casts = [
'tags' => 'array',
];
 
// ...
}

你也可以用分隔字符串保存 Tag 标签。要启用这种方法,在 separator() 方法传入分隔字符:

use Filament\Forms\Components\TagsInput;
 
TagsInput::make('tags')->separator(',')

标签输入框可以使用自动补全建议。要启用这个功能,在 suggestions() 方法中传入一个数组:

use Filament\Forms\Components\TagsInput;
 
TagsInput::make('tags')
->suggestions([
'tailwindcss',
'alpinejs',
'laravel',
'livewire',
])

Filament 也支持 spatie/laravel-tags。更多信息可查看插件文档

文本区

文本区(textarea)让你可以和多行字符串进行交互:

use Filament\Forms\Components\Textarea;
 
Textarea::make('description')

通过定义 rows()cols() 方法来调整文本区的大小:

use Filament\Forms\Components\Textarea;
 
Textarea::make('description')
->rows(10)
->cols(20)

你可以设置 minLength()maxLength() 方法限制字符串长度。这些方法同时添加了前端和后端验证器:

use Filament\Forms\Components\Textarea;
 
Textarea::make('description')
->minLength(50)
->maxLength(500)

键值对

键值对(key-value)字段让你可以与一维 JSON 对象进行交互:

use Filament\Forms\Components\KeyValue;
 
KeyValue::make('meta')

你可以使用 keyLable()valueLabel() 方法,自定义键值对字段的标签:

use Filament\Forms\Components\KeyValue;
 
KeyValue::make('meta')
->keyLabel('Property name')
->valueLabel('Property value')

你也可以禁止用户添加行,删除行,或者编辑行:

use Filament\Forms\Components\KeyValue;
 
KeyValue::make('meta')
->disableAddingRows()
->disableDeletingRows()
->disableEditingKeys()

你可以允许用户在表格中对行重新排序:

use Filament\Forms\Components\KeyValue;
 
KeyValue::make('meta')
->reorderable()

你也可以使用 keyPlaceholder()valuePlaceholder() 方法为键值对字段添加占位符:

use Filament\Forms\Components\KeyValue;
 
KeyValue::make('meta')
->keyPlaceholder('Property name')
->valuePlaceholder('Property value')

颜色选择器

颜色选择器(Color Picker)组件让你可以以一系列格式选择颜色。

默认情况下,组件使用 HEX(16 进制)格式:

use Filament\Forms\Components\ColorPicker;
 
ColorPicker::make('color')

另外,你可以使用不同格式:

use Filament\Forms\Components\ColorPicker;
 
ColorPicker::make('hsl_color')->hsl()
ColorPicker::make('rgb_color')->rgb()
ColorPicker::make('rgba_color')->rgba()

视图字段

除了创建自定义字段,你可以创造"视图(view)"字段,让你可以不需要创建另外的 PHP 类就可以创建自定义字段。

use Filament\Forms\Components\ViewField;
 
ViewField::make('notifications')->view('filament.forms.components.range-slider')

在你的视图内,你可以使用 Livewire 和 Alpine.js 与表单组件进行状态交互。

视图可以使用 $getStatePath() 闭包获取字段类的 Livewire 属性 path。你可以使用 wire:model 进行数据绑定,或者 $wire.entangle 与 Alpine.js 进行交互。

使用 Livewire's entangle 与 Alpine.js 共享 state:

<x-dynamic-component
:component="$getFieldWrapperView()"
:id="$getId()"
:label="$getLabel()"
:label-sr-only="$isLabelHidden()"
:helper-text="$getHelperText()"
:hint="$getHint()"
:hint-action="$getHintAction()"
:hint-color="$getHintColor()"
:hint-icon="$getHintIcon()"
:required="$isRequired()"
:state-path="$getStatePath()"
>
<div x-data="{ state: $wire.entangle('{{ $getStatePath() }}').defer }">
<!-- Interact with the `state` property in Alpine.js -->
</div>
</x-dynamic-component>

或者,你可以使用 wire:model 将其值绑定到 Livewire 属性:

<x-dynamic-component
:component="$getFieldWrapperView()"
:id="$getId()"
:label="$getLabel()"
:label-sr-only="$isLabelHidden()"
:helper-text="$getHelperText()"
:hint="$getHint()"
:hint-action="$getHintAction()"
:hint-color="$getHintColor()"
:hint-icon="$getHintIcon()"
:required="$isRequired()"
:state-path="$getStatePath()"
>
<input wire:model.defer="{{ $getStatePath() }}" />
</x-dynamic-component>

创建自定义字段

你也可以创建自定义的表单类和视图,用来在应用内复用,甚至向社区发布插件。

如果你只是需要创建一次性使用的简单自定义字段,你可以使用视图字段来渲染自定义模板文件。

要自定义表单字段类和视图,你可以使用以下命令:

php artisan make:form-field RangeSlider

该命令会创建如下字段类:

use Filament\Forms\Components\Field;
 
class RangeSlider extends Field
{
protected string $view = 'filament.forms.components.range-slider';
}

在你的视图内,你可以使用 Livewire 和 Alpine.js 与表单组件进行状态交互。

视图可以使用 $getStatePath() 闭包获取字段类的 Livewire 属性 path。你可以使用 wire:model 进行数据绑定,或者 $wire.entangle 与 Alpine.js 进行交互:

<x-dynamic-component
:component="$getFieldWrapperView()"
:id="$getId()"
:label="$getLabel()"
:label-sr-only="$isLabelHidden()"
:helper-text="$getHelperText()"
:hint="$getHint()"
:hint-action="$getHintAction()"
:hint-color="$getHintColor()"
:hint-icon="$getHintIcon()"
:required="$isRequired()"
:state-path="$getStatePath()"
>
<div x-data="{ state: $wire.entangle('{{ $getStatePath() }}').defer }">
<!-- Interact with the `state` property in Alpine.js -->
</div>
</x-dynamic-component>
Edit on GitHub

Still need help? Join our Discord community or open a GitHub discussion

上一页
开始
下一页
布局
, thousandsSeparator: ',', decimalPlaces: 2))

你也可以控制数字是否有符号。默认情况下,正数和负数都是允许的。isSigned: false 只允许正数:

use Filament\Forms\Components\TextInput;

TextInput::make('cost')->mask(fn (TextInput\Mask $mask) => $mask->money(prefix: '$', thousandsSeparator: ',', decimalPlaces: 2, isSigned: false))

Datalists

你可以使用 datalist() 方法为文本框指定一个 datalist 选项:

TextInput::make('manufacturer')
    ->datalist([
        'BWM',
        'Ford',
        'Mercedes-Benz',
        'Porsche',
        'Toyota',
        'Tesla',
        'Volkswagen',
    ])

Datalist 为用户提供文本框自动补全选项。不过,这些值只是单纯推荐,用户仍然可以输入任何值到文本框中。如果你想要限制定义选项,请用选择框

下拉列表

下拉列表组件让你可以使用一组预定义的选项:

use Filament\Forms\Components\Select;

Select::make('status')
    ->options([
        'draft' => 'Draft',
        'reviewing' => 'Reviewing',
        'published' => 'Published',
    ])

在选项中的数组,数组的键名会被保存,数组值则是每个下拉选项的标签。

你可以使用 searchable() 方法启用搜索输入框,使之更容易找到选项:

use Filament\Forms\Components\Select;

Select::make('authorId')
    ->label('Author')
    ->options(User::all()->pluck('name', 'id'))
    ->searchable()

如果你有很多选项,需要根据数据库搜索或者其他外部数据源填充数据,你可以使用 getSearchResultsUsing()getOptionLabelUsing() 方法代替 options()

getSearchResultsUsing() 方法接收一个回调函数作为参数,该回调以 $key => $value 格式返回搜索结果。

getSearchResultsUsing() 方法接收一个回调函数,该回调将选中的选项的 $value 转换成标签。

Select::make('authorId')
    ->searchable()
    ->getSearchResultsUsing(fn (string $searchQuery) => User::where('name', 'like', "%{$searchQuery}%")->limit(50)->pluck('name', 'id'))
    ->getOptionLabelUsing(fn ($value): ?string => User::find($value)?->name),

使用 disablePlaceholderSelection() 方法可以防止占位符被选中:

use Filament\Forms\Components\Select;

Select::make('status')
    ->options([
        'draft' => 'Draft',
        'reviewing' => 'Reviewing',
        'published' => 'Published',
    ])
    ->default('draft')
    ->disablePlaceholderSelection()

Multi-select

Select 组件上使用 multiple() 方法,允许你在下拉列表中进行多选:

use Filament\Forms\Components\Select;

Select::make('technologies')
    ->multiple()
    ->options([
        'tailwind' => 'Tailwind CSS',
        'alpine' => 'Alpine.js',
        'laravel' => 'Laravel',
        'livewire' => 'Laravel Livewire',
    ])

这些选项以 JSON 格式返回。如果你使用的是 Eloquent,你应该在模型属性中添加 array casts

use Illuminate\Database\Eloquent\Model;

class App extends Model
{
    protected $casts = [
        'technologies' => 'array',
    ];

    // ...
}

getOptionLabelsUsing() 方法可以用作对选中的选项值转成标签。注意,getOptionLabelUsing() 将被 getOptionLabelsUsing() 替换。

依赖下拉列表

通常情况下,你可能会需要用到"依赖"下拉列表,它基于其他字段控件的状态值填充选项。

高级表单区域提及的一些技术,需要使用依赖下拉列表。可使用这些技术对所有表单组件进行动态自定义。

从关联中自动加载数据

你可以使用 Selectrelationship() 方法,用以配置 BelongTo 关联模型,自动检索和保存选项:

use Filament\Forms\Components\Select;

Select::make('authorId')
    ->relationship('author', 'name')

multiple() 方法可与 relationship() 方法联合使用,用来从 BelongsToMany 关联中自动加载数据:

use Filament\Forms\Components\Select;

Select::make('technologies')
    ->multiple()
    ->relationship('technologies', 'name')

要启用这个功能,你必须按照关联字段区域的指南进行设置。如果你使用了后台面板,可以跳过此步。

你可以使用 relationship() 方法的第三个参数,自定义数据库查询:

use Filament\Forms\Components\Select;

Select::make('authorId')
    ->relationship('author', 'name')
    ->preload()

你可以使用 relationship() 方法的第三个参数来自定义数据库查询检索选项:

use Filament\Forms\Components\Select;
use Illuminate\Database\Eloquent\Builder;

Select::make('authorId')
    ->relationship('author', 'name', fn (Builder $query) => $query->withTrashed())

如果你想要自定义每个选项的标签,比如让其更具描述性、或者连接名和姓,你应该在数据库迁移中使用(virtual)虚拟字段:

$table->string('full_name')->virtualAs('concat(first_name, \' \', last_name)');
use Filament\Forms\Components\Select;

Select::make('authorId')
    ->relationship('author', 'full_name')

另外,你也可以使用 getOptionLabelFromRecordUsing() 方法将选中选项的 Eloquent 模型转换成标签。不过需要注意的是,这种方式比使用虚拟字段(virtual column)低效:

use Filament\Forms\Components\Select;
use Illuminate\Database\Eloquent\Model;

Select::make('authorId')
    ->relationship('author', 'first_name')
    ->getOptionLabelFromRecordUsing(fn (Model $record) => "{$record->first_name} {$record->last_name}")

处理 MorphTo 关联

MorphTo 关联比较特别,因为它使用户可以从一系列不同模型中选则记录。因此,有了 MorphToSelect 组件,实际上它不是一个 Select 字段,而是 Fieldset 中的两个 Select 字段。第一个 Select 字段允许你选择类型,第二个允许你选择对应类型的记录。

要使用 MorphToSelect,你必须将类型通过 types() 传入组件,使组件了解如何渲染不同类型选项:

use Filament\Forms\Components\MorphToSelect;

MorphToSelect::make('commentable')
    ->types([
        MorphToSelect\Type::make(Product::class)->titleColumnName('name'),
        MorphToSelect\Type::make(Post::class)->titleColumnName('title'),
    ])

titleColumnName() 被用作从 Product 或者 Post 中提取出标题。你也可以使用 getOptionLabelFromRecordUsing() 提取选项标签:

use Filament\Forms\Components\MorphToSelect;

MorphToSelect::make('commentable')
    ->types([
        MorphToSelect\Type::make(Product::class)
            ->getOptionLabelFromRecordUsing(fn (Product $record): string => "{$record->name} - {$record->slug}"),
        MorphToSelect\Type::make(Post::class)->titleColumnName('title'),
    ])

你也可以使用 modifyOptionsQueryUsing() 方法自定义数据查询检索选项:

use Filament\Forms\Components\MorphToSelect;
use Illuminate\Database\Eloquent\Builder;

MorphToSelect::make('commentable')
    ->types([
        MorphToSelect\Type::make(Product::class)
            ->titleColumnName('name')
            ->modifyOptionsQueryUsing(fn (Builder $query) => $query->whereBelongsTo($this->team)),
        MorphToSelect\Type::make(Post::class)
            ->titleColumnName('title')
            ->modifyOptionsQueryUsing(fn (Builder $query) => $query->whereBelongsTo($this->team)),
    ])

在 Select 字段中许多选项对于 MorphToSelect 都是可用的,包括 searchable()preload()allowHtml()optionsLimit()

创建新记录

你可以自定义表单,使之可以用来创建新纪录并附加到 BelongsTo 关联:

use Filament\Forms\Components\Select;
use Illuminate\Database\Eloquent\Model;

Select::make('authorId')
    ->relationship('author', 'name')
    ->createOptionForm([
        Forms\Components\TextInput::make('name')
            ->required(),
        Forms\Components\TextInput::make('email')
            ->required()
            ->email(),
    ]),

这个表单会在模态框内打开,用户可以在里面填写数据。一旦表单提交,新记录就会被字段选中。

由于 HTML 不支持嵌套 <form> 元素,你必须在视图的 <form> 表单之外渲染模态框。如果你使用后台面板,这已经被包含在内了:

<form wire:submit.prevent="submit">
    {{ $this->form }}
    
    <button type="submit">
        Submit
    </button>
</form>

{{ $this->modal }}

复选框

复选框(checkbox)组件,类似于 toggle,让你可以和布尔值交互。

use Filament\Forms\Components\Checkbox;

Checkbox::make('is_admin')

复选框字段有两种布局模式,inline 和 stacked。默认为 inline。

如果是 inline,标签会紧邻着复选框:

use Filament\Forms\Components\Checkbox;

Checkbox::make('is_admin')->inline()

如果是 stacked,标签会在复选框之上:

use Filament\Forms\Components\Checkbox;

Checkbox::make('is_admin')->inline(false)

如果你使用 Eloquent 保存布尔值,你应该添加 boolean casts 到模型属性中:

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    protected $casts = [
        'is_admin' => 'boolean',
    ];

    // ...
}

Toggle

Toggle 组件,类似于 复选框,用于和布尔值交互。

use Filament\Forms\Components\Toggle;

Toggle::make('is_admin')

Toggle 字段控件有两种布局模式,inline 和 stacked。默认是 inline(行内)。

如果是 inline,标签会紧挨着它:

use Filament\Forms\Components\Toggle;

Toggle::make('is_admin')->inline()

如果是 stacked,标签会在它上面:

use Filament\Forms\Components\Toggle;

Toggle::make('is_admin')->inline(false)

Toggle 也可以使用开/关图标。会被显示在手柄上,指示字段含义。参数必须是 Blade 模板图标组件:

use Filament\Forms\Components\Toggle;

Toggle::make('is_admin')
    ->onIcon('heroicon-s-lightning-bolt')
    ->offIcon('heroicon-s-user')

你也可以自定义每个状态显示的颜色。可用颜色包括 primarysecondarysuccesswarningdanger

use Filament\Forms\Components\Toggle;

Toggle::make('is_admin')
    ->onColor('success')
    ->offColor('danger')

如果你使用 Eloquent 保存布尔值,你应该添加 boolean casts 到相应的模型属性上。

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    protected $casts = [
        'is_admin' => 'boolean',
    ];

    // ...
}

复选框列表

复选框列表让你可以从一组预定义的选项中选择多个值:

use Filament\Forms\Components\CheckboxList;

CheckboxList::make('technologies')
    ->options([
        'tailwind' => 'TailwindCSS',
        'alpine' => 'Alpine.js',
        'laravel' => 'Laravel',
        'livewire' => 'Laravel Livewire',
    ])

这些选项以 JSON 格式返回。如果你使用 Eloquent 保存数据,你应该添加 array casts 到模型属性中:

use Illuminate\Database\Eloquent\Model;

class App extends Model
{
    protected $casts = [
        'technologies' => 'array',
    ];

    // ...
}

你也可以使用 columns() 方法将选项分成对应的列数:

use Filament\Forms\Components\CheckboxList;

CheckboxList::make('technologies')
    ->options([
        'tailwind' => 'TailwindCSS',
        'alpine' => 'Alpine.js',
        'laravel' => 'Laravel',
        'livewire' => 'Laravel Livewire',
    ])
    ->columns(2)

此方法像 gridcolumns() 方法一样,接收选项作为参数。你可以在不同的临界点中,以自适应的方式定制列数。

你也可以使用 bulkToggleable() 方法让用户一次性切换所有复选框:

use Filament\Forms\Components\CheckboxList;

CheckboxList::make('technologies')
    ->options([
        'tailwind' => 'Tailwind CSS',
        'alpine' => 'Alpine.js',
        'laravel' => 'Laravel',
        'livewire' => 'Laravel Livewire',
    ])
    ->bulkToggleable()

自动从关联中获取数据

你可以使用 relationship() 方法,配置关联模型用来自动检索和保存选项:

use Filament\Forms\Components\CheckboxList;

CheckboxList::make('technologies')
    ->relationship('technologies', 'name')

要启用这个功能,你必须按照关联字段区域的指南进行设置。如果你使用了后台面板,可以跳过此步。

你可以使用 relationship() 方法的第三个参数,自定义数据库查询检索选项:

use Filament\Forms\Components\CheckboxList;
use Illuminate\Database\Eloquent\Builder;

CheckboxList::make('technologies')
    ->relationship('technologies', 'name', fn (Builder $query) => $query->withTrashed())

如果你想要自定义每个选项的标签,比如让它更具描述性、或者连接名和姓,你应该在数据库迁移中使用(virtual)虚拟字段:

$table->string('full_name')->virtualAs('concat(first_name, \' \', last_name)');
use Filament\Forms\Components\CheckboxList;

CheckboxList::make('participants')
    ->relationship('participants', 'full_name')

另外,你也可以使用 getOptionLabelFromRecordUsing() 方法将选中选项的 Eloquent 模型转换成标签。不过需要注意的是,这种方式会比使用虚拟字段(virtual column)性能低:

use Filament\Forms\Components\CheckboxList;
use Illuminate\Database\Eloquent\Model;

CheckboxList::make('participants')
    ->relationship('participants', 'first_name')
    ->getOptionLabelFromRecordUsing(fn (Model $record) => "{$record->first_name} {$record->last_name}")

单选框

单选框提供单选按钮组,用来从一个预定义的选项列表中选择一个值:

use Filament\Forms\Components\Radio;

Radio::make('status')
    ->options([
        'draft' => 'Draft',
        'scheduled' => 'Scheduled',
        'published' => 'Published'
    ])

你可以使用 descriptions() 方法提供对每个选项的描述:

use Filament\Forms\Components\Radio;

Radio::make('status')
    ->options([
        'draft' => 'Draft',
        'scheduled' => 'Scheduled',
        'published' => 'Published'
    ])
    ->descriptions([
        'draft' => 'Is not visible.',
        'scheduled' => 'Will be visible.',
        'published' => 'Is visible.'
    ])

请确保在描述数组中使用和选项数组中同样的 键(key),这样描述才能和选项匹配。

如果你只是需要简单的布尔单选按钮组,带有"是/否"选项,你可以使用 boolean() 方法:

Radio::make('feedback')
    ->label('Do you like this post?')
    ->boolean()

你可以使用标签在行内(inline)显示选项:

Radio::make('feedback')
    ->label('Do you like this post?')
    ->boolean()
    ->inline()

日期时间选择器

日期时间选择器(Date-time Picker)提供了选择日期和时间的交互接口。

use Filament\Forms\Components\DatePicker;
use Filament\Forms\Components\DateTimePicker;
use Filament\Forms\Components\TimePicker;

DateTimePicker::make('published_at')
DatePicker::make('date_of_birth')
TimePicker::make('alarm_at')

你可以限制选择器可选的最小/最大日期。minDate()maxDate() 方法接收一个 DateTime 实例(如 Carbon)或字符串作为参数:

use Filament\Forms\Components\DatePicker;

DatePicker::make('date_of_birth')
    ->minDate(now()->subYears(150))
    ->maxDate(now())

你可以使用 format() 方法,自定义存入数据库时的字段格式。它接收字符串日期格式,使用 PHP 日期格式

use Filament\Forms\Components\DatePicker;

DatePicker::make('date_of_birth')->format('d/m/Y')

你可以自定义字段的显示格式,以不同于存入数据库时候的格式。对此,使用 displayFormat() 方法,它也可以接收字符串日期格式,使用 PHP 日期格式:

use Filament\Forms\Components\DatePicker;

DatePicker::make('date_of_birth')->displayFormat('d/m/Y')

当使用的是时间选择器时,你可以使用 withoutSeconds() 方法禁用秒输入框:

use Filament\Forms\Components\DateTimePicker;

DateTimePicker::make('published_at')->withoutSeconds()

你也可以使用 hoursStep()minutesStep()secondsStep() 方法,自定义输入小时/分钟/秒钟的增加间隔:

use Filament\Forms\Components\DateTimePicker;

DateTimePicker::make('published_at')
    ->hoursStep(2)
    ->minutesStep(15)
    ->secondsStep(10)

在某些国家,星期的第一天不是周一。使用 forms.components.date_time_picker.first_day_of_week 配置选项或者组件的 firstDayOfWeek() 方法,可以自定义时间选择器中星期的第一天。可接收的参数值从 0 到 7,周一是1,周日为 7 或 0:

use Filament\Forms\Components\DateTimePicker;

DateTimePicker::make('published_at')->firstDayOfWeek(7)

另外也有一些额外的便利方法,可以更方便地设置星期的第一天:

use Filament\Forms\Components\DateTimePicker;

DateTimePicker::make('published_at')->weekStartsOnMonday()
DateTimePicker::make('published_at')->weekStartsOnSunday()

要禁用特定的日期:

use Filament\Forms\Components\DateTimePicker;

DateTimePicker::make('date')
    ->label('Appointment date')
    ->minDate(now())
    ->maxDate(Carbon::now()->addDays(30))
    ->disabledDates(['2022-10-02', '2022-10-05', '2022-10-15'])

你可以使用 icon 方法修改日历图标:

use Filament\Forms\Components\DateTimePicker;

DateTimePicker::make('date')
    ->icon('heroicon-o-calendar')

此外,你也可以传入 false 移除图标:

use Filament\Forms\Components\DateTimePicker;

DateTimePicker::make('date')
    ->icon(false)

时区

你可以使用 timezone() 方法,让用户可以管理自己的时区:

use Filament\Forms\Components\DateTimePicker;

DateTimePicker::make('published_at')->timezone('America/New_York')

日期仍然会使用应用配置的时区保存,日期在加载时会适用新的时区,表单保存时会转换回系统配置的时区。

文件上传

文件上传字段基于 Filepond

use Filament\Forms\Components\FileUpload;

FileUpload::make('attachment')

默认情况下,文件会被公开上传到默认的存储盘中。

请注意,要正确地预览图片及其他文件,FilePond 要求从与应相同的域名提供文件,否则需要设置设置好 CORS 标头。请确保 APP_URL 环境变量设置正确,或者修改文件系统驱动,以设置正确的 URL。如果你将文件托管在其他域名中,比如 S3,请确保 CORS 表头设置正确。

可以使用 disk()directory()visibility() 方法,修改文件保存的磁盘和目录,以及可见性:

use Filament\Forms\Components\FileUpload;

FileUpload::make('attachment')
    ->disk('s3')
    ->directory('form-attachments')
    ->visibility('private')

请注意,由开发者决定是否将文件从磁盘上删除,因为 Filament 不知道其他地方是否也依赖于他。一种自动实现的方法是监听模型事件

默认情况下,新上传的文件会生成随机文件名。可以使用 preserveFilenames() 方法,保留上传文件的原文件名:

use Filament\Forms\Components\FileUpload;

FileUpload::make('attachment')->preserveFilenames()

你可以使用 getUploadedFileNameForStorageUsing() 方法,在回调函数中返回字符串,这样就可以完全自定义文件名怎么生成:

use Livewire\TemporaryUploadedFile;

FileUpload::make('attachment')
    ->getUploadedFileNameForStorageUsing(function (TemporaryUploadedFile $file): string {
        return (string) str($file->getClientOriginalName())->prepend('custom-prefix-');
    })

使用 storeFileNamesIn() 方法,你可以在保留原始文件名的同时,使用随机生成的文件名:

use Filament\Forms\Components\FileUpload;

FileUpload::make('attachments')
    ->multiple()
    ->storeFileNamesIn('attachment_file_names')

attachment_file_names 中会保存你上传文件的原始文件名。

你可以使用 acceptedFileTypes() 方法,传入 MIME 类型数组,来限制可以上传的文件类型。你也可以使用 image() 方法作为速记方法,允许所有图片的 MIME 类型。

use Filament\Forms\Components\FileUpload;

FileUpload::make('document')->acceptedFileTypes(['application/pdf'])
FileUpload::make('image')->image()

你也可以限制上传文件的大小,以 KB 计算:

use Filament\Forms\Components\FileUpload;

FileUpload::make('attachment')
    ->minSize(512)
    ->maxSize(1024)

要自定义 Livewire 默认的文件上传验证规则,包括最大 12MB 文件限制,请查阅相关文档

Filepond 允许你在上传之前对图片进行裁切或者调整大小。你可以使用 imageResizeMode()imageCropAspectRatio()imageResizeTargetHeight()imageResizeTargetWidth() 方法进行自定义。其他方法要生效,需先设置 imageResizeMode() - 将其设为 forcecovercontain

use Filament\Forms\Components\FileUpload;

FileUpload::make('image')
    ->image()
    ->imageResizeMode('cover')
    ->imageCropAspectRatio('16:9')
    ->imageResizeTargetWidth('1920')
    ->imageResizeTargetHeight('1080')

你也可以修改 Filepond 组件的一般外观。这些方法可用的选项可以在 Filepond 网站查看。

use Filament\Forms\Components\FileUpload;

FileUpload::make('attachment')
    ->imagePreviewHeight('250')
    ->loadingIndicatorPosition('left')
    ->panelAspectRatio('2:1')
    ->panelLayout('integrated')
    ->removeUploadedFileButtonPosition('right')
    ->uploadButtonPosition('left')
    ->uploadProgressIndicatorPosition('left')

你也可以上传多个文件。网址会以 JSON 方式保存:

use Filament\Forms\Components\FileUpload;

FileUpload::make('attachments')->multiple()

如果你使用 Eloquent 保存这些网址,你需要添加 array casts 到模型属性中:

use Illuminate\Database\Eloquent\Model;

class Message extends Model
{
    protected $casts = [
        'attachments' => 'array',
    ];

    // ...
}

使用 minFiles()maxFiles() 方法,你可以自定义文件上传的数量:

use Filament\Forms\Components\FileUpload;

FileUpload::make('attachments')
    ->multiple()
    ->minFiles(2)
    ->maxFiles(5)

使用 enableReordering() 方法,你也可以启用上传文件的重新排序功能:

use Filament\Forms\Components\FileUpload;

FileUpload::make('attachments')
    ->multipe()
    ->enableReordering()

使用 enableOpen() 方法,你可以添加按钮使文件可以在新的标签页中打开:

use Filament\Forms\Components\FileUpload;

FileUpload::make('attachments')
    ->multipe()
    ->enableOpen()

使用 enableDownload() 方法,你可以为每个上传文件添加一个下载按钮:

use Filament\Forms\Components\FileUpload;

FileUpload::make('attachments')
    ->multipe()
    ->enableDownload()

Filament 也支持 spatie/laravel-medialibrary。更多信息可查看插件文档

富文本编辑器

富文本编辑器让你可以编辑和预览 HTML 内容,上传图片。

use Filament\Forms\Components\RichEditor;

RichEditor::make('content')

你可以使用一系列便捷方法启用/禁用工具栏按钮:

use Filament\Forms\Components\RichEditor;

RichEditor::make('content')
    ->toolbarButtons([
        'attachFiles',
        'blockquote',
        'bold',
        'bulletList',
        'codeBlock',
        'h2',
        'h3',
        'italic',
        'link',
        'orderedList',
        'redo',
        'strike',
        'undo',
    ])
RichEditor::make('content')
    ->disableToolbarButtons([
        'attachFiles',
        'codeBlock',
    ])
RichEditor::make('content')
    ->disableAllToolbarButtons()
    ->enableToolbarButtons([
        'bold',
        'bulletList',
        'italic',
        'strike',
    ])

你可以使用配置方法自定义图片如何上传:

use Filament\Forms\Components\RichEditor;

RichEditor::make('content')
    ->fileAttachmentsDisk('s3')
    ->fileAttachmentsDirectory('attachments')
    ->fileAttachmentsVisibility('private')

Markdown 编辑器

Markdown 编辑器让你可以编辑和预览 markdown 内容,也可以上传图片。

use Filament\Forms\Components\MarkdownEditor;

MarkdownEditor::make('content')

你可以使用一系列便捷方法启用/禁用工具栏按钮:

use Filament\Forms\Components\MarkdownEditor;

MarkdownEditor::make('content')
    ->toolbarButtons([
        'attachFiles',
        'bold',
        'bulletList',
        'codeBlock',
        'edit',
        'italic',
        'link',
        'orderedList',
        'preview',
        'strike',
    ])
MarkdownEditor::make('content')
    ->disableToolbarButtons([
        'attachFiles',
        'codeBlock',
    ])
MarkdownEditor::make('content')
    ->disableAllToolbarButtons()
    ->enableToolbarButtons([
        'bold',
        'bulletList',
        'edit',
        'italic',
        'preview',
        'strike',
    ])

你可以使用配置方法自定义图片如何上传:

use Filament\Forms\Components\MarkdownEditor;

MarkdownEditor::make('content')
    ->fileAttachmentsDisk('s3')
    ->fileAttachmentsDirectory('attachments')
    ->fileAttachmentsVisibility('private')

Hidden

Hidden 组件让你可以在表单内创建一个带值的隐藏(hidden)字段。

use Filament\Forms\Components\Hidden;

Hidden::make('token')

Repeater

Repeater 组件让你在重复的表单组件中输出 JSON 数组。

use Filament\Forms\Components\Repeater;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;

Repeater::make('members')
    ->schema([
        TextInput::make('name')->required(),
        Select::make('role')
            ->options([
                'member' => 'Member',
                'administrator' => 'Administrator',
                'owner' => 'Owner',
            ])
            ->required(),
    ])
    ->columns(2)

我们建议将数据以 JSON 字段的形式保存在数据库中。另外,如果使用了 Eloquent,确保对该字段进行了 array 强制转换(casts)。

如上例所示,组件的 schema 可以在 schema() 方法中定义:

use Filament\Forms\Components\Repeater;
use Filament\Forms\Components\TextInput;

Repeater::make('members')
    ->schema([
        TextInput::make('name')->required(),
        // ...
    ])

如果你想要使用多重 schema 代码块定义 Repeater 并使之可以以任何顺序重复,请使用 builer

使用 defaultItems() 方法,Repeater 默认会有一些特定数量的空项目。

use Filament\Forms\Components\Repeater;

Repeater::make('members')
    ->schema([
        // ...
    ])
    ->defaultItems(3)

你可以设置标签,自定义显示在添加项目按钮上的文本。

use Filament\Forms\Components\Repeater;

Repeater::make('members')
    ->schema([
        // ...
    ])
    ->createItemButtonLabel('Add member')

你也可以阻止用户添加项目,删除项目或者在 Repeater 内移动项目:

use Filament\Forms\Components\Repeater;

Repeater::make('members')
    ->schema([
        // ...
    ])
    ->disableItemCreation()
    ->disableItemDeletion()
    ->disableItemMovement()

你可以使用 minItems()maxItems() 方法自定义创建的 Item 数量:

use Filament\Forms\Components\Repeater;

Repeater::make('members')
    ->schema([
        // ...
    ])
    ->minItems(1)
    ->maxItems(10)

可折叠

Repeater 可以是可折叠的 collapsible(), 用来在长表单中选择性隐藏内容:

use Filament\Forms\Components\Repeater;

Repeater::make('qualifications')
    ->schema([
        // ...
    ])
    ->collapsible()

你也可以让它在默认情况下是折叠的:

use Filament\Forms\Components\Repeater;

Repeater::make('qualifications')
    ->schema([
        // ...
    ])
    ->collapsed()

克隆项目

使用 cloneable() 方法,可以允许复制 repeater 项:

use Filament\Forms\Components\Repeater;

Repeater::make('qualifications')
    ->schema([
        // ...
    ])
    ->cloneable()

自动从关联中填充数据

你可以使用 Repeater 的 relationship() 方法配置关联,自动检索和保存 Repeater 数据:

use Filament\Forms\Components\Repeater;

Repeater::make('qualifications')
    ->relationship()
    ->schema([
        // ...
    ])

要启用该功能,你也必须按照关联字段区域的指示进行设置。如果你使用后台面板,可以忽略此步

排序项目

默认情况下,对 Repeater 项目进行排序是被禁用的。这是因为关联模型需要有一个 sort 字段,用来保存关联记录的顺序。要启用排序,你可以使用 orderable() 方法:

use Filament\Forms\Components\Repeater;

HasManyRepeater::make('qualifications')
    ->relationship('qualifications')
    ->schema([
        // ...
    ])
    ->orderable()

本例假定你的关联模型中有一个 sort 字段。

如果你使用了像 spatie/eloquent-sortable 这样的包,使用了像 order_column 这样的字段名作为排序字段,你可以将其作为参数传入 orderable() 中:

use Filament\Forms\Components\Repeater;

Repeater::make('qualifications')
    ->relationship('qualifications')
    ->schema([
        // ...
    ])
    ->orderable('order_column')

网格布局

你可以使用 grid() 方法组织 Repeater 项目:

use Filament\Forms\Components\Repeater;

Repeater::make('members')
    ->schema([
        // ...
    ])
    ->grid(2)

该方法与 gridcolumns() 方法相似,接收相同的参数选项。让你可以在不同临界点自定义网格列数。

项目标签

你可以使用 itemLabel() 方法,为 Repeater 项目添加标签:

use Filament\Forms\Components\Repeater;
use Filament\Forms\Components\TextInput;

Repeater::make('members')
    ->schema([
        TextInput::make('name')
            ->lazy(),
    ])
    ->itemLabel(fn (array $state): ?string => $state['name'] ?? null),

如果你希望项目标签动态更新,那么使用 $state 获取的字段,应该是 reactive()lazy() 的。

使用 $get() 访问父级字段值

所有表单组件都可以使用 $get()$set() 获取其他字段的值。然而,在 Repeater 中使用可能会碰到异常。

这是因为默认情况下,$get()$set() 被限定在当前 repeater 项目中。也就是说,你可以在 repeater 项目中的其他字段交互,而不需要了解该表单属于哪一个 repeater 条目。

其结果是,当你不能与 repeater 字段进行互动时,会感到困惑。我们使用 ../ 语法来解决此问题 - $get('../../parent_field_name')

假设你的表单数据结构如下:

[
    'client_id' => 1,

    'repeater' => [
        'item1' => [
            'service_id' => 2,
        ],
    ],
]

你需要在 repeater 项目中检索 client_id 的值。

$get() 用于检索当前的 repeater 项, 因此 $get('client_id') 意味着 $get('repeater.item1.client_id')

你可以使用 ../ 切换到数据结构的上一级,因此 $get('../client_id') 相当于 $get('repeater.client_id')$get('../../client_id') 相当于 $get('client_id')

Builder

类似于 Repeater,Builder 组件让你可以以 JSON 数组的形式输出重复的表单组件。所有不同的是,Repeater 只定义了一个需要重复的表单的 schema,而 Builder 允许定义多个 schema 代码块,你可以以任何顺序进行排序。这有助于创建更高级的数组结构。

Builder 组件的主要用途,是使用预定义的代码块来搭建网页内容。下例在页面内容中为不同的元素定义了多个代码块。在你网站的前端,你可以使用 JSON 或者你需要的格式遍历每个代码块。

use Filament\Forms\Components\Builder;
use Filament\Forms\Components\FileUpload;
use Filament\Forms\Components\MarkdownEditor;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;

Builder::make('content')
    ->blocks([
        Builder\Block::make('heading')
            ->schema([
                TextInput::make('content')
                    ->label('Heading')
                    ->required(),
                Select::make('level')
                    ->options([
                        'h1' => 'Heading 1',
                        'h2' => 'Heading 2',
                        'h3' => 'Heading 3',
                        'h4' => 'Heading 4',
                        'h5' => 'Heading 5',
                        'h6' => 'Heading 6',
                    ])
                    ->required(),
            ]),
        Builder\Block::make('paragraph')
            ->schema([
                MarkdownEditor::make('content')
                    ->label('Paragraph')
                    ->required(),
            ]),
        Builder\Block::make('image')
            ->schema([
                FileUpload::make('url')
                    ->label('Image')
                    ->image()
                    ->required(),
                TextInput::make('alt')
                    ->label('Alt text')
                    ->required(),
            ]),
    ])

建议在数据库中以 JSON 方式保存 Builder 的数据。另外,如果使用的是 Eloquent,确保对字段进行 array 造型。

如上例所示,代码块被定义在组件的 blocks() 方法中。代码块(Block) 是 Builder\Block 对象,有一个唯一名称以及一个组件 schema:

use Filament\Forms\Components\Builder;
use Filament\Forms\Components\TextInput;

Builder::make('content')
    ->blocks([
        Builder\Block::make('heading')
            ->schema([
                TextInput::make('content')->required(),
                // ...
            ]),
        // ...
    ])

默认情况下,代码块的标签会基于其名称自动生成。要重写代码块标签,请使用 label() 方法。如果你想使用本地化翻译字符,以此自定义标签是个有效的方式:

use Filament\Forms\Components\Builder;

Builder\Block::make('heading')->label(__('blocks.heading'))

Block 也可以添加图标,显示在标签旁边。icon() 方法接收 Blade 图标组件作为参数:

use Filament\Forms\Components\Builder;

Builder\Block::make('heading')->icon('heroicon-o-bookmark')

你也可以使用 minItems()maxItems() 方法自定义可以创建的项目数量:

use Filament\Forms\Components\Builder;
use Filament\Forms\Components\TextInput;

Builder::make('content')
    ->blocks([
        // ...
    ])
    ->minItems(1)
    ->maxItems(10)

可折叠

可以使用 collapsible() 方法,在长表单中选择性隐藏内容:

use Filament\Forms\Components\Builder;

Builder::make('content')
    ->blocks([
        // ...
    ])
    ->collapsible()

可以默认折叠所有项目:

use Filament\Forms\Components\Builder;

Builder::make('content')
    ->blocks([
        // ...
    ])
    ->collapsed()

标签输入框

标签(Tag)输入组件让你可以和标签列表交互。

默认情况下,标签以 JOSN 方式保存:

use Filament\Forms\Components\TagsInput;

TagsInput::make('tags')

如果你使用 Eloquent 保存 JSON 标签,你应该在模型属性中添加 array casts

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    protected $casts = [
        'tags' => 'array',
    ];

    // ...
}

你也可以用分隔字符串保存 Tag 标签。要启用这种方法,在 separator() 方法传入分隔字符:

use Filament\Forms\Components\TagsInput;

TagsInput::make('tags')->separator(',')

标签输入框可以使用自动补全建议。要启用这个功能,在 suggestions() 方法中传入一个数组:

use Filament\Forms\Components\TagsInput;

TagsInput::make('tags')
    ->suggestions([
        'tailwindcss',
        'alpinejs',
        'laravel',
        'livewire',
    ])

Filament 也支持 spatie/laravel-tags。更多信息可查看插件文档

文本区

文本区(textarea)让你可以和多行字符串进行交互:

use Filament\Forms\Components\Textarea;

Textarea::make('description')

通过定义 rows()cols() 方法来调整文本区的大小:

use Filament\Forms\Components\Textarea;

Textarea::make('description')
    ->rows(10)
    ->cols(20)

你可以设置 minLength()maxLength() 方法限制字符串长度。这些方法同时添加了前端和后端验证器:

use Filament\Forms\Components\Textarea;

Textarea::make('description')
    ->minLength(50)
    ->maxLength(500)

键值对

键值对(key-value)字段让你可以与一维 JSON 对象进行交互:

use Filament\Forms\Components\KeyValue;

KeyValue::make('meta')

你可以使用 keyLable()valueLabel() 方法,自定义键值对字段的标签:

use Filament\Forms\Components\KeyValue;

KeyValue::make('meta')
    ->keyLabel('Property name')
    ->valueLabel('Property value')

你也可以禁止用户添加行,删除行,或者编辑行:

use Filament\Forms\Components\KeyValue;

KeyValue::make('meta')
    ->disableAddingRows()
    ->disableDeletingRows()
    ->disableEditingKeys()

你可以允许用户在表格中对行重新排序:

use Filament\Forms\Components\KeyValue;

KeyValue::make('meta')
    ->reorderable()

你也可以使用 keyPlaceholder()valuePlaceholder() 方法为键值对字段添加占位符:

use Filament\Forms\Components\KeyValue;

KeyValue::make('meta')
    ->keyPlaceholder('Property name')
    ->valuePlaceholder('Property value')

颜色选择器

颜色选择器(Color Picker)组件让你可以以一系列格式选择颜色。

默认情况下,组件使用 HEX(16 进制)格式:

use Filament\Forms\Components\ColorPicker;

ColorPicker::make('color')

另外,你可以使用不同格式:

use Filament\Forms\Components\ColorPicker;

ColorPicker::make('hsl_color')->hsl()
ColorPicker::make('rgb_color')->rgb()
ColorPicker::make('rgba_color')->rgba()

视图字段

除了创建自定义字段,你可以创造"视图(view)"字段,让你可以不需要创建另外的 PHP 类就可以创建自定义字段。

use Filament\Forms\Components\ViewField;

ViewField::make('notifications')->view('filament.forms.components.range-slider')

在你的视图内,你可以使用 Livewire 和 Alpine.js 与表单组件进行状态交互。

视图可以使用 $getStatePath() 闭包获取字段类的 Livewire 属性 path。你可以使用 wire:model 进行数据绑定,或者 $wire.entangle 与 Alpine.js 进行交互。

使用 Livewire's entangle 与 Alpine.js 共享 state:

<x-dynamic-component
    :component="$getFieldWrapperView()"
    :id="$getId()"
    :label="$getLabel()"
    :label-sr-only="$isLabelHidden()"
    :helper-text="$getHelperText()"
    :hint="$getHint()"
    :hint-action="$getHintAction()"
    :hint-color="$getHintColor()"
    :hint-icon="$getHintIcon()"
    :required="$isRequired()"
    :state-path="$getStatePath()"
>
    <div x-data="{ state: $wire.entangle('{{ $getStatePath() }}').defer }">
        <!-- Interact with the `state` property in Alpine.js -->
    </div>
</x-dynamic-component>

或者,你可以使用 wire:model 将其值绑定到 Livewire 属性:

<x-dynamic-component
    :component="$getFieldWrapperView()"
    :id="$getId()"
    :label="$getLabel()"
    :label-sr-only="$isLabelHidden()"
    :helper-text="$getHelperText()"
    :hint="$getHint()"
    :hint-action="$getHintAction()"
    :hint-color="$getHintColor()"
    :hint-icon="$getHintIcon()"
    :required="$isRequired()"
    :state-path="$getStatePath()"
>
    <input wire:model.defer="{{ $getStatePath() }}" />
</x-dynamic-component>

创建自定义字段

你也可以创建自定义的表单类和视图,用来在应用内复用,甚至向社区发布插件。

如果你只是需要创建一次性使用的简单自定义字段,你可以使用视图字段来渲染自定义模板文件。

要自定义表单字段类和视图,你可以使用以下命令:

php artisan make:form-field RangeSlider

该命令会创建如下字段类:

use Filament\Forms\Components\Field;

class RangeSlider extends Field
{
    protected string $view = 'filament.forms.components.range-slider';
}

在你的视图内,你可以使用 Livewire 和 Alpine.js 与表单组件进行状态交互。

视图可以使用 $getStatePath() 闭包获取字段类的 Livewire 属性 path。你可以使用 wire:model 进行数据绑定,或者 $wire.entangle 与 Alpine.js 进行交互:

<x-dynamic-component
    :component="$getFieldWrapperView()"
    :id="$getId()"
    :label="$getLabel()"
    :label-sr-only="$isLabelHidden()"
    :helper-text="$getHelperText()"
    :hint="$getHint()"
    :hint-action="$getHintAction()"
    :hint-color="$getHintColor()"
    :hint-icon="$getHintIcon()"
    :required="$isRequired()"
    :state-path="$getStatePath()"
>
    <div x-data="{ state: $wire.entangle('{{ $getStatePath() }}').defer }">
        <!-- Interact with the `state` property in Alpine.js -->
    </div>
</x-dynamic-component>
Edit on GitHub

Still need help? Join our Discord community or open a GitHub discussion

上一页
开始
下一页
布局
, thousandsSeparator: ',', decimalPlaces: 2, isSigned: false))

Datalists

你可以使用 datalist() 方法为文本框指定一个 datalist 选项:

TextInput::make('manufacturer')
    ->datalist([
        'BWM',
        'Ford',
        'Mercedes-Benz',
        'Porsche',
        'Toyota',
        'Tesla',
        'Volkswagen',
    ])

Datalist 为用户提供文本框自动补全选项。不过,这些值只是单纯推荐,用户仍然可以输入任何值到文本框中。如果你想要限制定义选项,请用选择框

下拉列表

下拉列表组件让你可以使用一组预定义的选项:

use Filament\Forms\Components\Select;

Select::make('status')
    ->options([
        'draft' => 'Draft',
        'reviewing' => 'Reviewing',
        'published' => 'Published',
    ])

在选项中的数组,数组的键名会被保存,数组值则是每个下拉选项的标签。

你可以使用 searchable() 方法启用搜索输入框,使之更容易找到选项:

use Filament\Forms\Components\Select;

Select::make('authorId')
    ->label('Author')
    ->options(User::all()->pluck('name', 'id'))
    ->searchable()

如果你有很多选项,需要根据数据库搜索或者其他外部数据源填充数据,你可以使用 getSearchResultsUsing()getOptionLabelUsing() 方法代替 options()

getSearchResultsUsing() 方法接收一个回调函数作为参数,该回调以 $key => $value 格式返回搜索结果。

getSearchResultsUsing() 方法接收一个回调函数,该回调将选中的选项的 $value 转换成标签。

Select::make('authorId')
    ->searchable()
    ->getSearchResultsUsing(fn (string $searchQuery) => User::where('name', 'like', "%{$searchQuery}%")->limit(50)->pluck('name', 'id'))
    ->getOptionLabelUsing(fn ($value): ?string => User::find($value)?->name),

使用 disablePlaceholderSelection() 方法可以防止占位符被选中:

use Filament\Forms\Components\Select;

Select::make('status')
    ->options([
        'draft' => 'Draft',
        'reviewing' => 'Reviewing',
        'published' => 'Published',
    ])
    ->default('draft')
    ->disablePlaceholderSelection()

Multi-select

Select 组件上使用 multiple() 方法,允许你在下拉列表中进行多选:

use Filament\Forms\Components\Select;

Select::make('technologies')
    ->multiple()
    ->options([
        'tailwind' => 'Tailwind CSS',
        'alpine' => 'Alpine.js',
        'laravel' => 'Laravel',
        'livewire' => 'Laravel Livewire',
    ])

这些选项以 JSON 格式返回。如果你使用的是 Eloquent,你应该在模型属性中添加 array casts

use Illuminate\Database\Eloquent\Model;

class App extends Model
{
    protected $casts = [
        'technologies' => 'array',
    ];

    // ...
}

getOptionLabelsUsing() 方法可以用作对选中的选项值转成标签。注意,getOptionLabelUsing() 将被 getOptionLabelsUsing() 替换。

依赖下拉列表

通常情况下,你可能会需要用到"依赖"下拉列表,它基于其他字段控件的状态值填充选项。

高级表单区域提及的一些技术,需要使用依赖下拉列表。可使用这些技术对所有表单组件进行动态自定义。

从关联中自动加载数据

你可以使用 Selectrelationship() 方法,用以配置 BelongTo 关联模型,自动检索和保存选项:

use Filament\Forms\Components\Select;

Select::make('authorId')
    ->relationship('author', 'name')

multiple() 方法可与 relationship() 方法联合使用,用来从 BelongsToMany 关联中自动加载数据:

use Filament\Forms\Components\Select;

Select::make('technologies')
    ->multiple()
    ->relationship('technologies', 'name')

要启用这个功能,你必须按照关联字段区域的指南进行设置。如果你使用了后台面板,可以跳过此步。

你可以使用 relationship() 方法的第三个参数,自定义数据库查询:

use Filament\Forms\Components\Select;

Select::make('authorId')
    ->relationship('author', 'name')
    ->preload()

你可以使用 relationship() 方法的第三个参数来自定义数据库查询检索选项:

use Filament\Forms\Components\Select;
use Illuminate\Database\Eloquent\Builder;

Select::make('authorId')
    ->relationship('author', 'name', fn (Builder $query) => $query->withTrashed())

如果你想要自定义每个选项的标签,比如让其更具描述性、或者连接名和姓,你应该在数据库迁移中使用(virtual)虚拟字段:

$table->string('full_name')->virtualAs('concat(first_name, \' \', last_name)');
use Filament\Forms\Components\Select;

Select::make('authorId')
    ->relationship('author', 'full_name')

另外,你也可以使用 getOptionLabelFromRecordUsing() 方法将选中选项的 Eloquent 模型转换成标签。不过需要注意的是,这种方式比使用虚拟字段(virtual column)低效:

use Filament\Forms\Components\Select;
use Illuminate\Database\Eloquent\Model;

Select::make('authorId')
    ->relationship('author', 'first_name')
    ->getOptionLabelFromRecordUsing(fn (Model $record) => "{$record->first_name} {$record->last_name}")

处理 MorphTo 关联

MorphTo 关联比较特别,因为它使用户可以从一系列不同模型中选则记录。因此,有了 MorphToSelect 组件,实际上它不是一个 Select 字段,而是 Fieldset 中的两个 Select 字段。第一个 Select 字段允许你选择类型,第二个允许你选择对应类型的记录。

要使用 MorphToSelect,你必须将类型通过 types() 传入组件,使组件了解如何渲染不同类型选项:

use Filament\Forms\Components\MorphToSelect;

MorphToSelect::make('commentable')
    ->types([
        MorphToSelect\Type::make(Product::class)->titleColumnName('name'),
        MorphToSelect\Type::make(Post::class)->titleColumnName('title'),
    ])

titleColumnName() 被用作从 Product 或者 Post 中提取出标题。你也可以使用 getOptionLabelFromRecordUsing() 提取选项标签:

use Filament\Forms\Components\MorphToSelect;

MorphToSelect::make('commentable')
    ->types([
        MorphToSelect\Type::make(Product::class)
            ->getOptionLabelFromRecordUsing(fn (Product $record): string => "{$record->name} - {$record->slug}"),
        MorphToSelect\Type::make(Post::class)->titleColumnName('title'),
    ])

你也可以使用 modifyOptionsQueryUsing() 方法自定义数据查询检索选项:

use Filament\Forms\Components\MorphToSelect;
use Illuminate\Database\Eloquent\Builder;

MorphToSelect::make('commentable')
    ->types([
        MorphToSelect\Type::make(Product::class)
            ->titleColumnName('name')
            ->modifyOptionsQueryUsing(fn (Builder $query) => $query->whereBelongsTo($this->team)),
        MorphToSelect\Type::make(Post::class)
            ->titleColumnName('title')
            ->modifyOptionsQueryUsing(fn (Builder $query) => $query->whereBelongsTo($this->team)),
    ])

在 Select 字段中许多选项对于 MorphToSelect 都是可用的,包括 searchable()preload()allowHtml()optionsLimit()

创建新记录

你可以自定义表单,使之可以用来创建新纪录并附加到 BelongsTo 关联:

use Filament\Forms\Components\Select;
use Illuminate\Database\Eloquent\Model;

Select::make('authorId')
    ->relationship('author', 'name')
    ->createOptionForm([
        Forms\Components\TextInput::make('name')
            ->required(),
        Forms\Components\TextInput::make('email')
            ->required()
            ->email(),
    ]),

这个表单会在模态框内打开,用户可以在里面填写数据。一旦表单提交,新记录就会被字段选中。

由于 HTML 不支持嵌套 <form> 元素,你必须在视图的 <form> 表单之外渲染模态框。如果你使用后台面板,这已经被包含在内了:

<form wire:submit.prevent="submit">
    {{ $this->form }}
    
    <button type="submit">
        Submit
    </button>
</form>

{{ $this->modal }}

复选框

复选框(checkbox)组件,类似于 toggle,让你可以和布尔值交互。

use Filament\Forms\Components\Checkbox;

Checkbox::make('is_admin')

复选框字段有两种布局模式,inline 和 stacked。默认为 inline。

如果是 inline,标签会紧邻着复选框:

use Filament\Forms\Components\Checkbox;

Checkbox::make('is_admin')->inline()

如果是 stacked,标签会在复选框之上:

use Filament\Forms\Components\Checkbox;

Checkbox::make('is_admin')->inline(false)

如果你使用 Eloquent 保存布尔值,你应该添加 boolean casts 到模型属性中:

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    protected $casts = [
        'is_admin' => 'boolean',
    ];

    // ...
}

Toggle

Toggle 组件,类似于 复选框,用于和布尔值交互。

use Filament\Forms\Components\Toggle;

Toggle::make('is_admin')

Toggle 字段控件有两种布局模式,inline 和 stacked。默认是 inline(行内)。

如果是 inline,标签会紧挨着它:

use Filament\Forms\Components\Toggle;

Toggle::make('is_admin')->inline()

如果是 stacked,标签会在它上面:

use Filament\Forms\Components\Toggle;

Toggle::make('is_admin')->inline(false)

Toggle 也可以使用开/关图标。会被显示在手柄上,指示字段含义。参数必须是 Blade 模板图标组件:

use Filament\Forms\Components\Toggle;

Toggle::make('is_admin')
    ->onIcon('heroicon-s-lightning-bolt')
    ->offIcon('heroicon-s-user')

你也可以自定义每个状态显示的颜色。可用颜色包括 primarysecondarysuccesswarningdanger

use Filament\Forms\Components\Toggle;

Toggle::make('is_admin')
    ->onColor('success')
    ->offColor('danger')

如果你使用 Eloquent 保存布尔值,你应该添加 boolean casts 到相应的模型属性上。

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    protected $casts = [
        'is_admin' => 'boolean',
    ];

    // ...
}

复选框列表

复选框列表让你可以从一组预定义的选项中选择多个值:

use Filament\Forms\Components\CheckboxList;

CheckboxList::make('technologies')
    ->options([
        'tailwind' => 'TailwindCSS',
        'alpine' => 'Alpine.js',
        'laravel' => 'Laravel',
        'livewire' => 'Laravel Livewire',
    ])

这些选项以 JSON 格式返回。如果你使用 Eloquent 保存数据,你应该添加 array casts 到模型属性中:

use Illuminate\Database\Eloquent\Model;

class App extends Model
{
    protected $casts = [
        'technologies' => 'array',
    ];

    // ...
}

你也可以使用 columns() 方法将选项分成对应的列数:

use Filament\Forms\Components\CheckboxList;

CheckboxList::make('technologies')
    ->options([
        'tailwind' => 'TailwindCSS',
        'alpine' => 'Alpine.js',
        'laravel' => 'Laravel',
        'livewire' => 'Laravel Livewire',
    ])
    ->columns(2)

此方法像 gridcolumns() 方法一样,接收选项作为参数。你可以在不同的临界点中,以自适应的方式定制列数。

你也可以使用 bulkToggleable() 方法让用户一次性切换所有复选框:

use Filament\Forms\Components\CheckboxList;

CheckboxList::make('technologies')
    ->options([
        'tailwind' => 'Tailwind CSS',
        'alpine' => 'Alpine.js',
        'laravel' => 'Laravel',
        'livewire' => 'Laravel Livewire',
    ])
    ->bulkToggleable()

自动从关联中获取数据

你可以使用 relationship() 方法,配置关联模型用来自动检索和保存选项:

use Filament\Forms\Components\CheckboxList;

CheckboxList::make('technologies')
    ->relationship('technologies', 'name')

要启用这个功能,你必须按照关联字段区域的指南进行设置。如果你使用了后台面板,可以跳过此步。

你可以使用 relationship() 方法的第三个参数,自定义数据库查询检索选项:

use Filament\Forms\Components\CheckboxList;
use Illuminate\Database\Eloquent\Builder;

CheckboxList::make('technologies')
    ->relationship('technologies', 'name', fn (Builder $query) => $query->withTrashed())

如果你想要自定义每个选项的标签,比如让它更具描述性、或者连接名和姓,你应该在数据库迁移中使用(virtual)虚拟字段:

$table->string('full_name')->virtualAs('concat(first_name, \' \', last_name)');
use Filament\Forms\Components\CheckboxList;

CheckboxList::make('participants')
    ->relationship('participants', 'full_name')

另外,你也可以使用 getOptionLabelFromRecordUsing() 方法将选中选项的 Eloquent 模型转换成标签。不过需要注意的是,这种方式会比使用虚拟字段(virtual column)性能低:

use Filament\Forms\Components\CheckboxList;
use Illuminate\Database\Eloquent\Model;

CheckboxList::make('participants')
    ->relationship('participants', 'first_name')
    ->getOptionLabelFromRecordUsing(fn (Model $record) => "{$record->first_name} {$record->last_name}")

单选框

单选框提供单选按钮组,用来从一个预定义的选项列表中选择一个值:

use Filament\Forms\Components\Radio;

Radio::make('status')
    ->options([
        'draft' => 'Draft',
        'scheduled' => 'Scheduled',
        'published' => 'Published'
    ])

你可以使用 descriptions() 方法提供对每个选项的描述:

use Filament\Forms\Components\Radio;

Radio::make('status')
    ->options([
        'draft' => 'Draft',
        'scheduled' => 'Scheduled',
        'published' => 'Published'
    ])
    ->descriptions([
        'draft' => 'Is not visible.',
        'scheduled' => 'Will be visible.',
        'published' => 'Is visible.'
    ])

请确保在描述数组中使用和选项数组中同样的 键(key),这样描述才能和选项匹配。

如果你只是需要简单的布尔单选按钮组,带有"是/否"选项,你可以使用 boolean() 方法:

Radio::make('feedback')
    ->label('Do you like this post?')
    ->boolean()

你可以使用标签在行内(inline)显示选项:

Radio::make('feedback')
    ->label('Do you like this post?')
    ->boolean()
    ->inline()

日期时间选择器

日期时间选择器(Date-time Picker)提供了选择日期和时间的交互接口。

use Filament\Forms\Components\DatePicker;
use Filament\Forms\Components\DateTimePicker;
use Filament\Forms\Components\TimePicker;

DateTimePicker::make('published_at')
DatePicker::make('date_of_birth')
TimePicker::make('alarm_at')

你可以限制选择器可选的最小/最大日期。minDate()maxDate() 方法接收一个 DateTime 实例(如 Carbon)或字符串作为参数:

use Filament\Forms\Components\DatePicker;

DatePicker::make('date_of_birth')
    ->minDate(now()->subYears(150))
    ->maxDate(now())

你可以使用 format() 方法,自定义存入数据库时的字段格式。它接收字符串日期格式,使用 PHP 日期格式

use Filament\Forms\Components\DatePicker;

DatePicker::make('date_of_birth')->format('d/m/Y')

你可以自定义字段的显示格式,以不同于存入数据库时候的格式。对此,使用 displayFormat() 方法,它也可以接收字符串日期格式,使用 PHP 日期格式:

use Filament\Forms\Components\DatePicker;

DatePicker::make('date_of_birth')->displayFormat('d/m/Y')

当使用的是时间选择器时,你可以使用 withoutSeconds() 方法禁用秒输入框:

use Filament\Forms\Components\DateTimePicker;

DateTimePicker::make('published_at')->withoutSeconds()

你也可以使用 hoursStep()minutesStep()secondsStep() 方法,自定义输入小时/分钟/秒钟的增加间隔:

use Filament\Forms\Components\DateTimePicker;

DateTimePicker::make('published_at')
    ->hoursStep(2)
    ->minutesStep(15)
    ->secondsStep(10)

在某些国家,星期的第一天不是周一。使用 forms.components.date_time_picker.first_day_of_week 配置选项或者组件的 firstDayOfWeek() 方法,可以自定义时间选择器中星期的第一天。可接收的参数值从 0 到 7,周一是1,周日为 7 或 0:

use Filament\Forms\Components\DateTimePicker;

DateTimePicker::make('published_at')->firstDayOfWeek(7)

另外也有一些额外的便利方法,可以更方便地设置星期的第一天:

use Filament\Forms\Components\DateTimePicker;

DateTimePicker::make('published_at')->weekStartsOnMonday()
DateTimePicker::make('published_at')->weekStartsOnSunday()

要禁用特定的日期:

use Filament\Forms\Components\DateTimePicker;

DateTimePicker::make('date')
    ->label('Appointment date')
    ->minDate(now())
    ->maxDate(Carbon::now()->addDays(30))
    ->disabledDates(['2022-10-02', '2022-10-05', '2022-10-15'])

你可以使用 icon 方法修改日历图标:

use Filament\Forms\Components\DateTimePicker;

DateTimePicker::make('date')
    ->icon('heroicon-o-calendar')

此外,你也可以传入 false 移除图标:

use Filament\Forms\Components\DateTimePicker;

DateTimePicker::make('date')
    ->icon(false)

时区

你可以使用 timezone() 方法,让用户可以管理自己的时区:

use Filament\Forms\Components\DateTimePicker;

DateTimePicker::make('published_at')->timezone('America/New_York')

日期仍然会使用应用配置的时区保存,日期在加载时会适用新的时区,表单保存时会转换回系统配置的时区。

文件上传

文件上传字段基于 Filepond

use Filament\Forms\Components\FileUpload;

FileUpload::make('attachment')

默认情况下,文件会被公开上传到默认的存储盘中。

请注意,要正确地预览图片及其他文件,FilePond 要求从与应相同的域名提供文件,否则需要设置设置好 CORS 标头。请确保 APP_URL 环境变量设置正确,或者修改文件系统驱动,以设置正确的 URL。如果你将文件托管在其他域名中,比如 S3,请确保 CORS 表头设置正确。

可以使用 disk()directory()visibility() 方法,修改文件保存的磁盘和目录,以及可见性:

use Filament\Forms\Components\FileUpload;

FileUpload::make('attachment')
    ->disk('s3')
    ->directory('form-attachments')
    ->visibility('private')

请注意,由开发者决定是否将文件从磁盘上删除,因为 Filament 不知道其他地方是否也依赖于他。一种自动实现的方法是监听模型事件

默认情况下,新上传的文件会生成随机文件名。可以使用 preserveFilenames() 方法,保留上传文件的原文件名:

use Filament\Forms\Components\FileUpload;

FileUpload::make('attachment')->preserveFilenames()

你可以使用 getUploadedFileNameForStorageUsing() 方法,在回调函数中返回字符串,这样就可以完全自定义文件名怎么生成:

use Livewire\TemporaryUploadedFile;

FileUpload::make('attachment')
    ->getUploadedFileNameForStorageUsing(function (TemporaryUploadedFile $file): string {
        return (string) str($file->getClientOriginalName())->prepend('custom-prefix-');
    })

使用 storeFileNamesIn() 方法,你可以在保留原始文件名的同时,使用随机生成的文件名:

use Filament\Forms\Components\FileUpload;

FileUpload::make('attachments')
    ->multiple()
    ->storeFileNamesIn('attachment_file_names')

attachment_file_names 中会保存你上传文件的原始文件名。

你可以使用 acceptedFileTypes() 方法,传入 MIME 类型数组,来限制可以上传的文件类型。你也可以使用 image() 方法作为速记方法,允许所有图片的 MIME 类型。

use Filament\Forms\Components\FileUpload;

FileUpload::make('document')->acceptedFileTypes(['application/pdf'])
FileUpload::make('image')->image()

你也可以限制上传文件的大小,以 KB 计算:

use Filament\Forms\Components\FileUpload;

FileUpload::make('attachment')
    ->minSize(512)
    ->maxSize(1024)

要自定义 Livewire 默认的文件上传验证规则,包括最大 12MB 文件限制,请查阅相关文档

Filepond 允许你在上传之前对图片进行裁切或者调整大小。你可以使用 imageResizeMode()imageCropAspectRatio()imageResizeTargetHeight()imageResizeTargetWidth() 方法进行自定义。其他方法要生效,需先设置 imageResizeMode() - 将其设为 forcecovercontain

use Filament\Forms\Components\FileUpload;

FileUpload::make('image')
    ->image()
    ->imageResizeMode('cover')
    ->imageCropAspectRatio('16:9')
    ->imageResizeTargetWidth('1920')
    ->imageResizeTargetHeight('1080')

你也可以修改 Filepond 组件的一般外观。这些方法可用的选项可以在 Filepond 网站查看。

use Filament\Forms\Components\FileUpload;

FileUpload::make('attachment')
    ->imagePreviewHeight('250')
    ->loadingIndicatorPosition('left')
    ->panelAspectRatio('2:1')
    ->panelLayout('integrated')
    ->removeUploadedFileButtonPosition('right')
    ->uploadButtonPosition('left')
    ->uploadProgressIndicatorPosition('left')

你也可以上传多个文件。网址会以 JSON 方式保存:

use Filament\Forms\Components\FileUpload;

FileUpload::make('attachments')->multiple()

如果你使用 Eloquent 保存这些网址,你需要添加 array casts 到模型属性中:

use Illuminate\Database\Eloquent\Model;

class Message extends Model
{
    protected $casts = [
        'attachments' => 'array',
    ];

    // ...
}

使用 minFiles()maxFiles() 方法,你可以自定义文件上传的数量:

use Filament\Forms\Components\FileUpload;

FileUpload::make('attachments')
    ->multiple()
    ->minFiles(2)
    ->maxFiles(5)

使用 enableReordering() 方法,你也可以启用上传文件的重新排序功能:

use Filament\Forms\Components\FileUpload;

FileUpload::make('attachments')
    ->multipe()
    ->enableReordering()

使用 enableOpen() 方法,你可以添加按钮使文件可以在新的标签页中打开:

use Filament\Forms\Components\FileUpload;

FileUpload::make('attachments')
    ->multipe()
    ->enableOpen()

使用 enableDownload() 方法,你可以为每个上传文件添加一个下载按钮:

use Filament\Forms\Components\FileUpload;

FileUpload::make('attachments')
    ->multipe()
    ->enableDownload()

Filament 也支持 spatie/laravel-medialibrary。更多信息可查看插件文档

富文本编辑器

富文本编辑器让你可以编辑和预览 HTML 内容,上传图片。

use Filament\Forms\Components\RichEditor;

RichEditor::make('content')

你可以使用一系列便捷方法启用/禁用工具栏按钮:

use Filament\Forms\Components\RichEditor;

RichEditor::make('content')
    ->toolbarButtons([
        'attachFiles',
        'blockquote',
        'bold',
        'bulletList',
        'codeBlock',
        'h2',
        'h3',
        'italic',
        'link',
        'orderedList',
        'redo',
        'strike',
        'undo',
    ])
RichEditor::make('content')
    ->disableToolbarButtons([
        'attachFiles',
        'codeBlock',
    ])
RichEditor::make('content')
    ->disableAllToolbarButtons()
    ->enableToolbarButtons([
        'bold',
        'bulletList',
        'italic',
        'strike',
    ])

你可以使用配置方法自定义图片如何上传:

use Filament\Forms\Components\RichEditor;

RichEditor::make('content')
    ->fileAttachmentsDisk('s3')
    ->fileAttachmentsDirectory('attachments')
    ->fileAttachmentsVisibility('private')

Markdown 编辑器

Markdown 编辑器让你可以编辑和预览 markdown 内容,也可以上传图片。

use Filament\Forms\Components\MarkdownEditor;

MarkdownEditor::make('content')

你可以使用一系列便捷方法启用/禁用工具栏按钮:

use Filament\Forms\Components\MarkdownEditor;

MarkdownEditor::make('content')
    ->toolbarButtons([
        'attachFiles',
        'bold',
        'bulletList',
        'codeBlock',
        'edit',
        'italic',
        'link',
        'orderedList',
        'preview',
        'strike',
    ])
MarkdownEditor::make('content')
    ->disableToolbarButtons([
        'attachFiles',
        'codeBlock',
    ])
MarkdownEditor::make('content')
    ->disableAllToolbarButtons()
    ->enableToolbarButtons([
        'bold',
        'bulletList',
        'edit',
        'italic',
        'preview',
        'strike',
    ])

你可以使用配置方法自定义图片如何上传:

use Filament\Forms\Components\MarkdownEditor;

MarkdownEditor::make('content')
    ->fileAttachmentsDisk('s3')
    ->fileAttachmentsDirectory('attachments')
    ->fileAttachmentsVisibility('private')

Hidden

Hidden 组件让你可以在表单内创建一个带值的隐藏(hidden)字段。

use Filament\Forms\Components\Hidden;

Hidden::make('token')

Repeater

Repeater 组件让你在重复的表单组件中输出 JSON 数组。

use Filament\Forms\Components\Repeater;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;

Repeater::make('members')
    ->schema([
        TextInput::make('name')->required(),
        Select::make('role')
            ->options([
                'member' => 'Member',
                'administrator' => 'Administrator',
                'owner' => 'Owner',
            ])
            ->required(),
    ])
    ->columns(2)

我们建议将数据以 JSON 字段的形式保存在数据库中。另外,如果使用了 Eloquent,确保对该字段进行了 array 强制转换(casts)。

如上例所示,组件的 schema 可以在 schema() 方法中定义:

use Filament\Forms\Components\Repeater;
use Filament\Forms\Components\TextInput;

Repeater::make('members')
    ->schema([
        TextInput::make('name')->required(),
        // ...
    ])

如果你想要使用多重 schema 代码块定义 Repeater 并使之可以以任何顺序重复,请使用 builer

使用 defaultItems() 方法,Repeater 默认会有一些特定数量的空项目。

use Filament\Forms\Components\Repeater;

Repeater::make('members')
    ->schema([
        // ...
    ])
    ->defaultItems(3)

你可以设置标签,自定义显示在添加项目按钮上的文本。

use Filament\Forms\Components\Repeater;

Repeater::make('members')
    ->schema([
        // ...
    ])
    ->createItemButtonLabel('Add member')

你也可以阻止用户添加项目,删除项目或者在 Repeater 内移动项目:

use Filament\Forms\Components\Repeater;

Repeater::make('members')
    ->schema([
        // ...
    ])
    ->disableItemCreation()
    ->disableItemDeletion()
    ->disableItemMovement()

你可以使用 minItems()maxItems() 方法自定义创建的 Item 数量:

use Filament\Forms\Components\Repeater;

Repeater::make('members')
    ->schema([
        // ...
    ])
    ->minItems(1)
    ->maxItems(10)

可折叠

Repeater 可以是可折叠的 collapsible(), 用来在长表单中选择性隐藏内容:

use Filament\Forms\Components\Repeater;

Repeater::make('qualifications')
    ->schema([
        // ...
    ])
    ->collapsible()

你也可以让它在默认情况下是折叠的:

use Filament\Forms\Components\Repeater;

Repeater::make('qualifications')
    ->schema([
        // ...
    ])
    ->collapsed()

克隆项目

使用 cloneable() 方法,可以允许复制 repeater 项:

use Filament\Forms\Components\Repeater;

Repeater::make('qualifications')
    ->schema([
        // ...
    ])
    ->cloneable()

自动从关联中填充数据

你可以使用 Repeater 的 relationship() 方法配置关联,自动检索和保存 Repeater 数据:

use Filament\Forms\Components\Repeater;

Repeater::make('qualifications')
    ->relationship()
    ->schema([
        // ...
    ])

要启用该功能,你也必须按照关联字段区域的指示进行设置。如果你使用后台面板,可以忽略此步

排序项目

默认情况下,对 Repeater 项目进行排序是被禁用的。这是因为关联模型需要有一个 sort 字段,用来保存关联记录的顺序。要启用排序,你可以使用 orderable() 方法:

use Filament\Forms\Components\Repeater;

HasManyRepeater::make('qualifications')
    ->relationship('qualifications')
    ->schema([
        // ...
    ])
    ->orderable()

本例假定你的关联模型中有一个 sort 字段。

如果你使用了像 spatie/eloquent-sortable 这样的包,使用了像 order_column 这样的字段名作为排序字段,你可以将其作为参数传入 orderable() 中:

use Filament\Forms\Components\Repeater;

Repeater::make('qualifications')
    ->relationship('qualifications')
    ->schema([
        // ...
    ])
    ->orderable('order_column')

网格布局

你可以使用 grid() 方法组织 Repeater 项目:

use Filament\Forms\Components\Repeater;

Repeater::make('members')
    ->schema([
        // ...
    ])
    ->grid(2)

该方法与 gridcolumns() 方法相似,接收相同的参数选项。让你可以在不同临界点自定义网格列数。

项目标签

你可以使用 itemLabel() 方法,为 Repeater 项目添加标签:

use Filament\Forms\Components\Repeater;
use Filament\Forms\Components\TextInput;

Repeater::make('members')
    ->schema([
        TextInput::make('name')
            ->lazy(),
    ])
    ->itemLabel(fn (array $state): ?string => $state['name'] ?? null),

如果你希望项目标签动态更新,那么使用 $state 获取的字段,应该是 reactive()lazy() 的。

使用 $get() 访问父级字段值

所有表单组件都可以使用 $get()$set() 获取其他字段的值。然而,在 Repeater 中使用可能会碰到异常。

这是因为默认情况下,$get()$set() 被限定在当前 repeater 项目中。也就是说,你可以在 repeater 项目中的其他字段交互,而不需要了解该表单属于哪一个 repeater 条目。

其结果是,当你不能与 repeater 字段进行互动时,会感到困惑。我们使用 ../ 语法来解决此问题 - $get('../../parent_field_name')

假设你的表单数据结构如下:

[
    'client_id' => 1,

    'repeater' => [
        'item1' => [
            'service_id' => 2,
        ],
    ],
]

你需要在 repeater 项目中检索 client_id 的值。

$get() 用于检索当前的 repeater 项, 因此 $get('client_id') 意味着 $get('repeater.item1.client_id')

你可以使用 ../ 切换到数据结构的上一级,因此 $get('../client_id') 相当于 $get('repeater.client_id')$get('../../client_id') 相当于 $get('client_id')

Builder

类似于 Repeater,Builder 组件让你可以以 JSON 数组的形式输出重复的表单组件。所有不同的是,Repeater 只定义了一个需要重复的表单的 schema,而 Builder 允许定义多个 schema 代码块,你可以以任何顺序进行排序。这有助于创建更高级的数组结构。

Builder 组件的主要用途,是使用预定义的代码块来搭建网页内容。下例在页面内容中为不同的元素定义了多个代码块。在你网站的前端,你可以使用 JSON 或者你需要的格式遍历每个代码块。

use Filament\Forms\Components\Builder;
use Filament\Forms\Components\FileUpload;
use Filament\Forms\Components\MarkdownEditor;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;

Builder::make('content')
    ->blocks([
        Builder\Block::make('heading')
            ->schema([
                TextInput::make('content')
                    ->label('Heading')
                    ->required(),
                Select::make('level')
                    ->options([
                        'h1' => 'Heading 1',
                        'h2' => 'Heading 2',
                        'h3' => 'Heading 3',
                        'h4' => 'Heading 4',
                        'h5' => 'Heading 5',
                        'h6' => 'Heading 6',
                    ])
                    ->required(),
            ]),
        Builder\Block::make('paragraph')
            ->schema([
                MarkdownEditor::make('content')
                    ->label('Paragraph')
                    ->required(),
            ]),
        Builder\Block::make('image')
            ->schema([
                FileUpload::make('url')
                    ->label('Image')
                    ->image()
                    ->required(),
                TextInput::make('alt')
                    ->label('Alt text')
                    ->required(),
            ]),
    ])

建议在数据库中以 JSON 方式保存 Builder 的数据。另外,如果使用的是 Eloquent,确保对字段进行 array 造型。

如上例所示,代码块被定义在组件的 blocks() 方法中。代码块(Block) 是 Builder\Block 对象,有一个唯一名称以及一个组件 schema:

use Filament\Forms\Components\Builder;
use Filament\Forms\Components\TextInput;

Builder::make('content')
    ->blocks([
        Builder\Block::make('heading')
            ->schema([
                TextInput::make('content')->required(),
                // ...
            ]),
        // ...
    ])

默认情况下,代码块的标签会基于其名称自动生成。要重写代码块标签,请使用 label() 方法。如果你想使用本地化翻译字符,以此自定义标签是个有效的方式:

use Filament\Forms\Components\Builder;

Builder\Block::make('heading')->label(__('blocks.heading'))

Block 也可以添加图标,显示在标签旁边。icon() 方法接收 Blade 图标组件作为参数:

use Filament\Forms\Components\Builder;

Builder\Block::make('heading')->icon('heroicon-o-bookmark')

你也可以使用 minItems()maxItems() 方法自定义可以创建的项目数量:

use Filament\Forms\Components\Builder;
use Filament\Forms\Components\TextInput;

Builder::make('content')
    ->blocks([
        // ...
    ])
    ->minItems(1)
    ->maxItems(10)

可折叠

可以使用 collapsible() 方法,在长表单中选择性隐藏内容:

use Filament\Forms\Components\Builder;

Builder::make('content')
    ->blocks([
        // ...
    ])
    ->collapsible()

可以默认折叠所有项目:

use Filament\Forms\Components\Builder;

Builder::make('content')
    ->blocks([
        // ...
    ])
    ->collapsed()

标签输入框

标签(Tag)输入组件让你可以和标签列表交互。

默认情况下,标签以 JOSN 方式保存:

use Filament\Forms\Components\TagsInput;

TagsInput::make('tags')

如果你使用 Eloquent 保存 JSON 标签,你应该在模型属性中添加 array casts

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    protected $casts = [
        'tags' => 'array',
    ];

    // ...
}

你也可以用分隔字符串保存 Tag 标签。要启用这种方法,在 separator() 方法传入分隔字符:

use Filament\Forms\Components\TagsInput;

TagsInput::make('tags')->separator(',')

标签输入框可以使用自动补全建议。要启用这个功能,在 suggestions() 方法中传入一个数组:

use Filament\Forms\Components\TagsInput;

TagsInput::make('tags')
    ->suggestions([
        'tailwindcss',
        'alpinejs',
        'laravel',
        'livewire',
    ])

Filament 也支持 spatie/laravel-tags。更多信息可查看插件文档

文本区

文本区(textarea)让你可以和多行字符串进行交互:

use Filament\Forms\Components\Textarea;

Textarea::make('description')

通过定义 rows()cols() 方法来调整文本区的大小:

use Filament\Forms\Components\Textarea;

Textarea::make('description')
    ->rows(10)
    ->cols(20)

你可以设置 minLength()maxLength() 方法限制字符串长度。这些方法同时添加了前端和后端验证器:

use Filament\Forms\Components\Textarea;

Textarea::make('description')
    ->minLength(50)
    ->maxLength(500)

键值对

键值对(key-value)字段让你可以与一维 JSON 对象进行交互:

use Filament\Forms\Components\KeyValue;

KeyValue::make('meta')

你可以使用 keyLable()valueLabel() 方法,自定义键值对字段的标签:

use Filament\Forms\Components\KeyValue;

KeyValue::make('meta')
    ->keyLabel('Property name')
    ->valueLabel('Property value')

你也可以禁止用户添加行,删除行,或者编辑行:

use Filament\Forms\Components\KeyValue;

KeyValue::make('meta')
    ->disableAddingRows()
    ->disableDeletingRows()
    ->disableEditingKeys()

你可以允许用户在表格中对行重新排序:

use Filament\Forms\Components\KeyValue;

KeyValue::make('meta')
    ->reorderable()

你也可以使用 keyPlaceholder()valuePlaceholder() 方法为键值对字段添加占位符:

use Filament\Forms\Components\KeyValue;

KeyValue::make('meta')
    ->keyPlaceholder('Property name')
    ->valuePlaceholder('Property value')

颜色选择器

颜色选择器(Color Picker)组件让你可以以一系列格式选择颜色。

默认情况下,组件使用 HEX(16 进制)格式:

use Filament\Forms\Components\ColorPicker;

ColorPicker::make('color')

另外,你可以使用不同格式:

use Filament\Forms\Components\ColorPicker;

ColorPicker::make('hsl_color')->hsl()
ColorPicker::make('rgb_color')->rgb()
ColorPicker::make('rgba_color')->rgba()

视图字段

除了创建自定义字段,你可以创造"视图(view)"字段,让你可以不需要创建另外的 PHP 类就可以创建自定义字段。

use Filament\Forms\Components\ViewField;

ViewField::make('notifications')->view('filament.forms.components.range-slider')

在你的视图内,你可以使用 Livewire 和 Alpine.js 与表单组件进行状态交互。

视图可以使用 $getStatePath() 闭包获取字段类的 Livewire 属性 path。你可以使用 wire:model 进行数据绑定,或者 $wire.entangle 与 Alpine.js 进行交互。

使用 Livewire's entangle 与 Alpine.js 共享 state:

<x-dynamic-component
    :component="$getFieldWrapperView()"
    :id="$getId()"
    :label="$getLabel()"
    :label-sr-only="$isLabelHidden()"
    :helper-text="$getHelperText()"
    :hint="$getHint()"
    :hint-action="$getHintAction()"
    :hint-color="$getHintColor()"
    :hint-icon="$getHintIcon()"
    :required="$isRequired()"
    :state-path="$getStatePath()"
>
    <div x-data="{ state: $wire.entangle('{{ $getStatePath() }}').defer }">
        <!-- Interact with the `state` property in Alpine.js -->
    </div>
</x-dynamic-component>

或者,你可以使用 wire:model 将其值绑定到 Livewire 属性:

<x-dynamic-component
    :component="$getFieldWrapperView()"
    :id="$getId()"
    :label="$getLabel()"
    :label-sr-only="$isLabelHidden()"
    :helper-text="$getHelperText()"
    :hint="$getHint()"
    :hint-action="$getHintAction()"
    :hint-color="$getHintColor()"
    :hint-icon="$getHintIcon()"
    :required="$isRequired()"
    :state-path="$getStatePath()"
>
    <input wire:model.defer="{{ $getStatePath() }}" />
</x-dynamic-component>

创建自定义字段

你也可以创建自定义的表单类和视图,用来在应用内复用,甚至向社区发布插件。

如果你只是需要创建一次性使用的简单自定义字段,你可以使用视图字段来渲染自定义模板文件。

要自定义表单字段类和视图,你可以使用以下命令:

php artisan make:form-field RangeSlider

该命令会创建如下字段类:

use Filament\Forms\Components\Field;

class RangeSlider extends Field
{
    protected string $view = 'filament.forms.components.range-slider';
}

在你的视图内,你可以使用 Livewire 和 Alpine.js 与表单组件进行状态交互。

视图可以使用 $getStatePath() 闭包获取字段类的 Livewire 属性 path。你可以使用 wire:model 进行数据绑定,或者 $wire.entangle 与 Alpine.js 进行交互:

<x-dynamic-component
    :component="$getFieldWrapperView()"
    :id="$getId()"
    :label="$getLabel()"
    :label-sr-only="$isLabelHidden()"
    :helper-text="$getHelperText()"
    :hint="$getHint()"
    :hint-action="$getHintAction()"
    :hint-color="$getHintColor()"
    :hint-icon="$getHintIcon()"
    :required="$isRequired()"
    :state-path="$getStatePath()"
>
    <div x-data="{ state: $wire.entangle('{{ $getStatePath() }}').defer }">
        <!-- Interact with the `state` property in Alpine.js -->
    </div>
</x-dynamic-component>
Edit on GitHub

Still need help? Join our Discord community or open a GitHub discussion

上一页
开始
下一页
布局
, thousandsSeparator: ',', decimalPlaces: 2))

你也可以控制数字是否有符号。默认情况下,正数和负数都是允许的。isSigned: false 只允许正数:

use Filament\Forms\Components\TextInput;

TextInput::make('cost')->mask(fn (TextInput\Mask $mask) => $mask->money(prefix: '$', thousandsSeparator: ',', decimalPlaces: 2, isSigned: false))

Datalists

你可以使用 datalist() 方法为文本框指定一个 datalist 选项:

TextInput::make('manufacturer')
    ->datalist([
        'BWM',
        'Ford',
        'Mercedes-Benz',
        'Porsche',
        'Toyota',
        'Tesla',
        'Volkswagen',
    ])

Datalist 为用户提供文本框自动补全选项。不过,这些值只是单纯推荐,用户仍然可以输入任何值到文本框中。如果你想要限制定义选项,请用选择框

下拉列表

下拉列表组件让你可以使用一组预定义的选项:

use Filament\Forms\Components\Select;

Select::make('status')
    ->options([
        'draft' => 'Draft',
        'reviewing' => 'Reviewing',
        'published' => 'Published',
    ])

在选项中的数组,数组的键名会被保存,数组值则是每个下拉选项的标签。

你可以使用 searchable() 方法启用搜索输入框,使之更容易找到选项:

use Filament\Forms\Components\Select;

Select::make('authorId')
    ->label('Author')
    ->options(User::all()->pluck('name', 'id'))
    ->searchable()

如果你有很多选项,需要根据数据库搜索或者其他外部数据源填充数据,你可以使用 getSearchResultsUsing()getOptionLabelUsing() 方法代替 options()

getSearchResultsUsing() 方法接收一个回调函数作为参数,该回调以 $key => $value 格式返回搜索结果。

getSearchResultsUsing() 方法接收一个回调函数,该回调将选中的选项的 $value 转换成标签。

Select::make('authorId')
    ->searchable()
    ->getSearchResultsUsing(fn (string $searchQuery) => User::where('name', 'like', "%{$searchQuery}%")->limit(50)->pluck('name', 'id'))
    ->getOptionLabelUsing(fn ($value): ?string => User::find($value)?->name),

使用 disablePlaceholderSelection() 方法可以防止占位符被选中:

use Filament\Forms\Components\Select;

Select::make('status')
    ->options([
        'draft' => 'Draft',
        'reviewing' => 'Reviewing',
        'published' => 'Published',
    ])
    ->default('draft')
    ->disablePlaceholderSelection()

Multi-select

Select 组件上使用 multiple() 方法,允许你在下拉列表中进行多选:

use Filament\Forms\Components\Select;

Select::make('technologies')
    ->multiple()
    ->options([
        'tailwind' => 'Tailwind CSS',
        'alpine' => 'Alpine.js',
        'laravel' => 'Laravel',
        'livewire' => 'Laravel Livewire',
    ])

这些选项以 JSON 格式返回。如果你使用的是 Eloquent,你应该在模型属性中添加 array casts

use Illuminate\Database\Eloquent\Model;

class App extends Model
{
    protected $casts = [
        'technologies' => 'array',
    ];

    // ...
}

getOptionLabelsUsing() 方法可以用作对选中的选项值转成标签。注意,getOptionLabelUsing() 将被 getOptionLabelsUsing() 替换。

依赖下拉列表

通常情况下,你可能会需要用到"依赖"下拉列表,它基于其他字段控件的状态值填充选项。

高级表单区域提及的一些技术,需要使用依赖下拉列表。可使用这些技术对所有表单组件进行动态自定义。

从关联中自动加载数据

你可以使用 Selectrelationship() 方法,用以配置 BelongTo 关联模型,自动检索和保存选项:

use Filament\Forms\Components\Select;

Select::make('authorId')
    ->relationship('author', 'name')

multiple() 方法可与 relationship() 方法联合使用,用来从 BelongsToMany 关联中自动加载数据:

use Filament\Forms\Components\Select;

Select::make('technologies')
    ->multiple()
    ->relationship('technologies', 'name')

要启用这个功能,你必须按照关联字段区域的指南进行设置。如果你使用了后台面板,可以跳过此步。

你可以使用 relationship() 方法的第三个参数,自定义数据库查询:

use Filament\Forms\Components\Select;

Select::make('authorId')
    ->relationship('author', 'name')
    ->preload()

你可以使用 relationship() 方法的第三个参数来自定义数据库查询检索选项:

use Filament\Forms\Components\Select;
use Illuminate\Database\Eloquent\Builder;

Select::make('authorId')
    ->relationship('author', 'name', fn (Builder $query) => $query->withTrashed())

如果你想要自定义每个选项的标签,比如让其更具描述性、或者连接名和姓,你应该在数据库迁移中使用(virtual)虚拟字段:

$table->string('full_name')->virtualAs('concat(first_name, \' \', last_name)');
use Filament\Forms\Components\Select;

Select::make('authorId')
    ->relationship('author', 'full_name')

另外,你也可以使用 getOptionLabelFromRecordUsing() 方法将选中选项的 Eloquent 模型转换成标签。不过需要注意的是,这种方式比使用虚拟字段(virtual column)低效:

use Filament\Forms\Components\Select;
use Illuminate\Database\Eloquent\Model;

Select::make('authorId')
    ->relationship('author', 'first_name')
    ->getOptionLabelFromRecordUsing(fn (Model $record) => "{$record->first_name} {$record->last_name}")

处理 MorphTo 关联

MorphTo 关联比较特别,因为它使用户可以从一系列不同模型中选则记录。因此,有了 MorphToSelect 组件,实际上它不是一个 Select 字段,而是 Fieldset 中的两个 Select 字段。第一个 Select 字段允许你选择类型,第二个允许你选择对应类型的记录。

要使用 MorphToSelect,你必须将类型通过 types() 传入组件,使组件了解如何渲染不同类型选项:

use Filament\Forms\Components\MorphToSelect;

MorphToSelect::make('commentable')
    ->types([
        MorphToSelect\Type::make(Product::class)->titleColumnName('name'),
        MorphToSelect\Type::make(Post::class)->titleColumnName('title'),
    ])

titleColumnName() 被用作从 Product 或者 Post 中提取出标题。你也可以使用 getOptionLabelFromRecordUsing() 提取选项标签:

use Filament\Forms\Components\MorphToSelect;

MorphToSelect::make('commentable')
    ->types([
        MorphToSelect\Type::make(Product::class)
            ->getOptionLabelFromRecordUsing(fn (Product $record): string => "{$record->name} - {$record->slug}"),
        MorphToSelect\Type::make(Post::class)->titleColumnName('title'),
    ])

你也可以使用 modifyOptionsQueryUsing() 方法自定义数据查询检索选项:

use Filament\Forms\Components\MorphToSelect;
use Illuminate\Database\Eloquent\Builder;

MorphToSelect::make('commentable')
    ->types([
        MorphToSelect\Type::make(Product::class)
            ->titleColumnName('name')
            ->modifyOptionsQueryUsing(fn (Builder $query) => $query->whereBelongsTo($this->team)),
        MorphToSelect\Type::make(Post::class)
            ->titleColumnName('title')
            ->modifyOptionsQueryUsing(fn (Builder $query) => $query->whereBelongsTo($this->team)),
    ])

在 Select 字段中许多选项对于 MorphToSelect 都是可用的,包括 searchable()preload()allowHtml()optionsLimit()

创建新记录

你可以自定义表单,使之可以用来创建新纪录并附加到 BelongsTo 关联:

use Filament\Forms\Components\Select;
use Illuminate\Database\Eloquent\Model;

Select::make('authorId')
    ->relationship('author', 'name')
    ->createOptionForm([
        Forms\Components\TextInput::make('name')
            ->required(),
        Forms\Components\TextInput::make('email')
            ->required()
            ->email(),
    ]),

这个表单会在模态框内打开,用户可以在里面填写数据。一旦表单提交,新记录就会被字段选中。

由于 HTML 不支持嵌套 <form> 元素,你必须在视图的 <form> 表单之外渲染模态框。如果你使用后台面板,这已经被包含在内了:

<form wire:submit.prevent="submit">
    {{ $this->form }}
    
    <button type="submit">
        Submit
    </button>
</form>

{{ $this->modal }}

复选框

复选框(checkbox)组件,类似于 toggle,让你可以和布尔值交互。

use Filament\Forms\Components\Checkbox;

Checkbox::make('is_admin')

复选框字段有两种布局模式,inline 和 stacked。默认为 inline。

如果是 inline,标签会紧邻着复选框:

use Filament\Forms\Components\Checkbox;

Checkbox::make('is_admin')->inline()

如果是 stacked,标签会在复选框之上:

use Filament\Forms\Components\Checkbox;

Checkbox::make('is_admin')->inline(false)

如果你使用 Eloquent 保存布尔值,你应该添加 boolean casts 到模型属性中:

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    protected $casts = [
        'is_admin' => 'boolean',
    ];

    // ...
}

Toggle

Toggle 组件,类似于 复选框,用于和布尔值交互。

use Filament\Forms\Components\Toggle;

Toggle::make('is_admin')

Toggle 字段控件有两种布局模式,inline 和 stacked。默认是 inline(行内)。

如果是 inline,标签会紧挨着它:

use Filament\Forms\Components\Toggle;

Toggle::make('is_admin')->inline()

如果是 stacked,标签会在它上面:

use Filament\Forms\Components\Toggle;

Toggle::make('is_admin')->inline(false)

Toggle 也可以使用开/关图标。会被显示在手柄上,指示字段含义。参数必须是 Blade 模板图标组件:

use Filament\Forms\Components\Toggle;

Toggle::make('is_admin')
    ->onIcon('heroicon-s-lightning-bolt')
    ->offIcon('heroicon-s-user')

你也可以自定义每个状态显示的颜色。可用颜色包括 primarysecondarysuccesswarningdanger

use Filament\Forms\Components\Toggle;

Toggle::make('is_admin')
    ->onColor('success')
    ->offColor('danger')

如果你使用 Eloquent 保存布尔值,你应该添加 boolean casts 到相应的模型属性上。

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    protected $casts = [
        'is_admin' => 'boolean',
    ];

    // ...
}

复选框列表

复选框列表让你可以从一组预定义的选项中选择多个值:

use Filament\Forms\Components\CheckboxList;

CheckboxList::make('technologies')
    ->options([
        'tailwind' => 'TailwindCSS',
        'alpine' => 'Alpine.js',
        'laravel' => 'Laravel',
        'livewire' => 'Laravel Livewire',
    ])

这些选项以 JSON 格式返回。如果你使用 Eloquent 保存数据,你应该添加 array casts 到模型属性中:

use Illuminate\Database\Eloquent\Model;

class App extends Model
{
    protected $casts = [
        'technologies' => 'array',
    ];

    // ...
}

你也可以使用 columns() 方法将选项分成对应的列数:

use Filament\Forms\Components\CheckboxList;

CheckboxList::make('technologies')
    ->options([
        'tailwind' => 'TailwindCSS',
        'alpine' => 'Alpine.js',
        'laravel' => 'Laravel',
        'livewire' => 'Laravel Livewire',
    ])
    ->columns(2)

此方法像 gridcolumns() 方法一样,接收选项作为参数。你可以在不同的临界点中,以自适应的方式定制列数。

你也可以使用 bulkToggleable() 方法让用户一次性切换所有复选框:

use Filament\Forms\Components\CheckboxList;

CheckboxList::make('technologies')
    ->options([
        'tailwind' => 'Tailwind CSS',
        'alpine' => 'Alpine.js',
        'laravel' => 'Laravel',
        'livewire' => 'Laravel Livewire',
    ])
    ->bulkToggleable()

自动从关联中获取数据

你可以使用 relationship() 方法,配置关联模型用来自动检索和保存选项:

use Filament\Forms\Components\CheckboxList;

CheckboxList::make('technologies')
    ->relationship('technologies', 'name')

要启用这个功能,你必须按照关联字段区域的指南进行设置。如果你使用了后台面板,可以跳过此步。

你可以使用 relationship() 方法的第三个参数,自定义数据库查询检索选项:

use Filament\Forms\Components\CheckboxList;
use Illuminate\Database\Eloquent\Builder;

CheckboxList::make('technologies')
    ->relationship('technologies', 'name', fn (Builder $query) => $query->withTrashed())

如果你想要自定义每个选项的标签,比如让它更具描述性、或者连接名和姓,你应该在数据库迁移中使用(virtual)虚拟字段:

$table->string('full_name')->virtualAs('concat(first_name, \' \', last_name)');
use Filament\Forms\Components\CheckboxList;

CheckboxList::make('participants')
    ->relationship('participants', 'full_name')

另外,你也可以使用 getOptionLabelFromRecordUsing() 方法将选中选项的 Eloquent 模型转换成标签。不过需要注意的是,这种方式会比使用虚拟字段(virtual column)性能低:

use Filament\Forms\Components\CheckboxList;
use Illuminate\Database\Eloquent\Model;

CheckboxList::make('participants')
    ->relationship('participants', 'first_name')
    ->getOptionLabelFromRecordUsing(fn (Model $record) => "{$record->first_name} {$record->last_name}")

单选框

单选框提供单选按钮组,用来从一个预定义的选项列表中选择一个值:

use Filament\Forms\Components\Radio;

Radio::make('status')
    ->options([
        'draft' => 'Draft',
        'scheduled' => 'Scheduled',
        'published' => 'Published'
    ])

你可以使用 descriptions() 方法提供对每个选项的描述:

use Filament\Forms\Components\Radio;

Radio::make('status')
    ->options([
        'draft' => 'Draft',
        'scheduled' => 'Scheduled',
        'published' => 'Published'
    ])
    ->descriptions([
        'draft' => 'Is not visible.',
        'scheduled' => 'Will be visible.',
        'published' => 'Is visible.'
    ])

请确保在描述数组中使用和选项数组中同样的 键(key),这样描述才能和选项匹配。

如果你只是需要简单的布尔单选按钮组,带有"是/否"选项,你可以使用 boolean() 方法:

Radio::make('feedback')
    ->label('Do you like this post?')
    ->boolean()

你可以使用标签在行内(inline)显示选项:

Radio::make('feedback')
    ->label('Do you like this post?')
    ->boolean()
    ->inline()

日期时间选择器

日期时间选择器(Date-time Picker)提供了选择日期和时间的交互接口。

use Filament\Forms\Components\DatePicker;
use Filament\Forms\Components\DateTimePicker;
use Filament\Forms\Components\TimePicker;

DateTimePicker::make('published_at')
DatePicker::make('date_of_birth')
TimePicker::make('alarm_at')

你可以限制选择器可选的最小/最大日期。minDate()maxDate() 方法接收一个 DateTime 实例(如 Carbon)或字符串作为参数:

use Filament\Forms\Components\DatePicker;

DatePicker::make('date_of_birth')
    ->minDate(now()->subYears(150))
    ->maxDate(now())

你可以使用 format() 方法,自定义存入数据库时的字段格式。它接收字符串日期格式,使用 PHP 日期格式

use Filament\Forms\Components\DatePicker;

DatePicker::make('date_of_birth')->format('d/m/Y')

你可以自定义字段的显示格式,以不同于存入数据库时候的格式。对此,使用 displayFormat() 方法,它也可以接收字符串日期格式,使用 PHP 日期格式:

use Filament\Forms\Components\DatePicker;

DatePicker::make('date_of_birth')->displayFormat('d/m/Y')

当使用的是时间选择器时,你可以使用 withoutSeconds() 方法禁用秒输入框:

use Filament\Forms\Components\DateTimePicker;

DateTimePicker::make('published_at')->withoutSeconds()

你也可以使用 hoursStep()minutesStep()secondsStep() 方法,自定义输入小时/分钟/秒钟的增加间隔:

use Filament\Forms\Components\DateTimePicker;

DateTimePicker::make('published_at')
    ->hoursStep(2)
    ->minutesStep(15)
    ->secondsStep(10)

在某些国家,星期的第一天不是周一。使用 forms.components.date_time_picker.first_day_of_week 配置选项或者组件的 firstDayOfWeek() 方法,可以自定义时间选择器中星期的第一天。可接收的参数值从 0 到 7,周一是1,周日为 7 或 0:

use Filament\Forms\Components\DateTimePicker;

DateTimePicker::make('published_at')->firstDayOfWeek(7)

另外也有一些额外的便利方法,可以更方便地设置星期的第一天:

use Filament\Forms\Components\DateTimePicker;

DateTimePicker::make('published_at')->weekStartsOnMonday()
DateTimePicker::make('published_at')->weekStartsOnSunday()

要禁用特定的日期:

use Filament\Forms\Components\DateTimePicker;

DateTimePicker::make('date')
    ->label('Appointment date')
    ->minDate(now())
    ->maxDate(Carbon::now()->addDays(30))
    ->disabledDates(['2022-10-02', '2022-10-05', '2022-10-15'])

你可以使用 icon 方法修改日历图标:

use Filament\Forms\Components\DateTimePicker;

DateTimePicker::make('date')
    ->icon('heroicon-o-calendar')

此外,你也可以传入 false 移除图标:

use Filament\Forms\Components\DateTimePicker;

DateTimePicker::make('date')
    ->icon(false)

时区

你可以使用 timezone() 方法,让用户可以管理自己的时区:

use Filament\Forms\Components\DateTimePicker;

DateTimePicker::make('published_at')->timezone('America/New_York')

日期仍然会使用应用配置的时区保存,日期在加载时会适用新的时区,表单保存时会转换回系统配置的时区。

文件上传

文件上传字段基于 Filepond

use Filament\Forms\Components\FileUpload;

FileUpload::make('attachment')

默认情况下,文件会被公开上传到默认的存储盘中。

请注意,要正确地预览图片及其他文件,FilePond 要求从与应相同的域名提供文件,否则需要设置设置好 CORS 标头。请确保 APP_URL 环境变量设置正确,或者修改文件系统驱动,以设置正确的 URL。如果你将文件托管在其他域名中,比如 S3,请确保 CORS 表头设置正确。

可以使用 disk()directory()visibility() 方法,修改文件保存的磁盘和目录,以及可见性:

use Filament\Forms\Components\FileUpload;

FileUpload::make('attachment')
    ->disk('s3')
    ->directory('form-attachments')
    ->visibility('private')

请注意,由开发者决定是否将文件从磁盘上删除,因为 Filament 不知道其他地方是否也依赖于他。一种自动实现的方法是监听模型事件

默认情况下,新上传的文件会生成随机文件名。可以使用 preserveFilenames() 方法,保留上传文件的原文件名:

use Filament\Forms\Components\FileUpload;

FileUpload::make('attachment')->preserveFilenames()

你可以使用 getUploadedFileNameForStorageUsing() 方法,在回调函数中返回字符串,这样就可以完全自定义文件名怎么生成:

use Livewire\TemporaryUploadedFile;

FileUpload::make('attachment')
    ->getUploadedFileNameForStorageUsing(function (TemporaryUploadedFile $file): string {
        return (string) str($file->getClientOriginalName())->prepend('custom-prefix-');
    })

使用 storeFileNamesIn() 方法,你可以在保留原始文件名的同时,使用随机生成的文件名:

use Filament\Forms\Components\FileUpload;

FileUpload::make('attachments')
    ->multiple()
    ->storeFileNamesIn('attachment_file_names')

attachment_file_names 中会保存你上传文件的原始文件名。

你可以使用 acceptedFileTypes() 方法,传入 MIME 类型数组,来限制可以上传的文件类型。你也可以使用 image() 方法作为速记方法,允许所有图片的 MIME 类型。

use Filament\Forms\Components\FileUpload;

FileUpload::make('document')->acceptedFileTypes(['application/pdf'])
FileUpload::make('image')->image()

你也可以限制上传文件的大小,以 KB 计算:

use Filament\Forms\Components\FileUpload;

FileUpload::make('attachment')
    ->minSize(512)
    ->maxSize(1024)

要自定义 Livewire 默认的文件上传验证规则,包括最大 12MB 文件限制,请查阅相关文档

Filepond 允许你在上传之前对图片进行裁切或者调整大小。你可以使用 imageResizeMode()imageCropAspectRatio()imageResizeTargetHeight()imageResizeTargetWidth() 方法进行自定义。其他方法要生效,需先设置 imageResizeMode() - 将其设为 forcecovercontain

use Filament\Forms\Components\FileUpload;

FileUpload::make('image')
    ->image()
    ->imageResizeMode('cover')
    ->imageCropAspectRatio('16:9')
    ->imageResizeTargetWidth('1920')
    ->imageResizeTargetHeight('1080')

你也可以修改 Filepond 组件的一般外观。这些方法可用的选项可以在 Filepond 网站查看。

use Filament\Forms\Components\FileUpload;

FileUpload::make('attachment')
    ->imagePreviewHeight('250')
    ->loadingIndicatorPosition('left')
    ->panelAspectRatio('2:1')
    ->panelLayout('integrated')
    ->removeUploadedFileButtonPosition('right')
    ->uploadButtonPosition('left')
    ->uploadProgressIndicatorPosition('left')

你也可以上传多个文件。网址会以 JSON 方式保存:

use Filament\Forms\Components\FileUpload;

FileUpload::make('attachments')->multiple()

如果你使用 Eloquent 保存这些网址,你需要添加 array casts 到模型属性中:

use Illuminate\Database\Eloquent\Model;

class Message extends Model
{
    protected $casts = [
        'attachments' => 'array',
    ];

    // ...
}

使用 minFiles()maxFiles() 方法,你可以自定义文件上传的数量:

use Filament\Forms\Components\FileUpload;

FileUpload::make('attachments')
    ->multiple()
    ->minFiles(2)
    ->maxFiles(5)

使用 enableReordering() 方法,你也可以启用上传文件的重新排序功能:

use Filament\Forms\Components\FileUpload;

FileUpload::make('attachments')
    ->multipe()
    ->enableReordering()

使用 enableOpen() 方法,你可以添加按钮使文件可以在新的标签页中打开:

use Filament\Forms\Components\FileUpload;

FileUpload::make('attachments')
    ->multipe()
    ->enableOpen()

使用 enableDownload() 方法,你可以为每个上传文件添加一个下载按钮:

use Filament\Forms\Components\FileUpload;

FileUpload::make('attachments')
    ->multipe()
    ->enableDownload()

Filament 也支持 spatie/laravel-medialibrary。更多信息可查看插件文档

富文本编辑器

富文本编辑器让你可以编辑和预览 HTML 内容,上传图片。

use Filament\Forms\Components\RichEditor;

RichEditor::make('content')

你可以使用一系列便捷方法启用/禁用工具栏按钮:

use Filament\Forms\Components\RichEditor;

RichEditor::make('content')
    ->toolbarButtons([
        'attachFiles',
        'blockquote',
        'bold',
        'bulletList',
        'codeBlock',
        'h2',
        'h3',
        'italic',
        'link',
        'orderedList',
        'redo',
        'strike',
        'undo',
    ])
RichEditor::make('content')
    ->disableToolbarButtons([
        'attachFiles',
        'codeBlock',
    ])
RichEditor::make('content')
    ->disableAllToolbarButtons()
    ->enableToolbarButtons([
        'bold',
        'bulletList',
        'italic',
        'strike',
    ])

你可以使用配置方法自定义图片如何上传:

use Filament\Forms\Components\RichEditor;

RichEditor::make('content')
    ->fileAttachmentsDisk('s3')
    ->fileAttachmentsDirectory('attachments')
    ->fileAttachmentsVisibility('private')

Markdown 编辑器

Markdown 编辑器让你可以编辑和预览 markdown 内容,也可以上传图片。

use Filament\Forms\Components\MarkdownEditor;

MarkdownEditor::make('content')

你可以使用一系列便捷方法启用/禁用工具栏按钮:

use Filament\Forms\Components\MarkdownEditor;

MarkdownEditor::make('content')
    ->toolbarButtons([
        'attachFiles',
        'bold',
        'bulletList',
        'codeBlock',
        'edit',
        'italic',
        'link',
        'orderedList',
        'preview',
        'strike',
    ])
MarkdownEditor::make('content')
    ->disableToolbarButtons([
        'attachFiles',
        'codeBlock',
    ])
MarkdownEditor::make('content')
    ->disableAllToolbarButtons()
    ->enableToolbarButtons([
        'bold',
        'bulletList',
        'edit',
        'italic',
        'preview',
        'strike',
    ])

你可以使用配置方法自定义图片如何上传:

use Filament\Forms\Components\MarkdownEditor;

MarkdownEditor::make('content')
    ->fileAttachmentsDisk('s3')
    ->fileAttachmentsDirectory('attachments')
    ->fileAttachmentsVisibility('private')

Hidden

Hidden 组件让你可以在表单内创建一个带值的隐藏(hidden)字段。

use Filament\Forms\Components\Hidden;

Hidden::make('token')

Repeater

Repeater 组件让你在重复的表单组件中输出 JSON 数组。

use Filament\Forms\Components\Repeater;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;

Repeater::make('members')
    ->schema([
        TextInput::make('name')->required(),
        Select::make('role')
            ->options([
                'member' => 'Member',
                'administrator' => 'Administrator',
                'owner' => 'Owner',
            ])
            ->required(),
    ])
    ->columns(2)

我们建议将数据以 JSON 字段的形式保存在数据库中。另外,如果使用了 Eloquent,确保对该字段进行了 array 强制转换(casts)。

如上例所示,组件的 schema 可以在 schema() 方法中定义:

use Filament\Forms\Components\Repeater;
use Filament\Forms\Components\TextInput;

Repeater::make('members')
    ->schema([
        TextInput::make('name')->required(),
        // ...
    ])

如果你想要使用多重 schema 代码块定义 Repeater 并使之可以以任何顺序重复,请使用 builer

使用 defaultItems() 方法,Repeater 默认会有一些特定数量的空项目。

use Filament\Forms\Components\Repeater;

Repeater::make('members')
    ->schema([
        // ...
    ])
    ->defaultItems(3)

你可以设置标签,自定义显示在添加项目按钮上的文本。

use Filament\Forms\Components\Repeater;

Repeater::make('members')
    ->schema([
        // ...
    ])
    ->createItemButtonLabel('Add member')

你也可以阻止用户添加项目,删除项目或者在 Repeater 内移动项目:

use Filament\Forms\Components\Repeater;

Repeater::make('members')
    ->schema([
        // ...
    ])
    ->disableItemCreation()
    ->disableItemDeletion()
    ->disableItemMovement()

你可以使用 minItems()maxItems() 方法自定义创建的 Item 数量:

use Filament\Forms\Components\Repeater;

Repeater::make('members')
    ->schema([
        // ...
    ])
    ->minItems(1)
    ->maxItems(10)

可折叠

Repeater 可以是可折叠的 collapsible(), 用来在长表单中选择性隐藏内容:

use Filament\Forms\Components\Repeater;

Repeater::make('qualifications')
    ->schema([
        // ...
    ])
    ->collapsible()

你也可以让它在默认情况下是折叠的:

use Filament\Forms\Components\Repeater;

Repeater::make('qualifications')
    ->schema([
        // ...
    ])
    ->collapsed()

克隆项目

使用 cloneable() 方法,可以允许复制 repeater 项:

use Filament\Forms\Components\Repeater;

Repeater::make('qualifications')
    ->schema([
        // ...
    ])
    ->cloneable()

自动从关联中填充数据

你可以使用 Repeater 的 relationship() 方法配置关联,自动检索和保存 Repeater 数据:

use Filament\Forms\Components\Repeater;

Repeater::make('qualifications')
    ->relationship()
    ->schema([
        // ...
    ])

要启用该功能,你也必须按照关联字段区域的指示进行设置。如果你使用后台面板,可以忽略此步

排序项目

默认情况下,对 Repeater 项目进行排序是被禁用的。这是因为关联模型需要有一个 sort 字段,用来保存关联记录的顺序。要启用排序,你可以使用 orderable() 方法:

use Filament\Forms\Components\Repeater;

HasManyRepeater::make('qualifications')
    ->relationship('qualifications')
    ->schema([
        // ...
    ])
    ->orderable()

本例假定你的关联模型中有一个 sort 字段。

如果你使用了像 spatie/eloquent-sortable 这样的包,使用了像 order_column 这样的字段名作为排序字段,你可以将其作为参数传入 orderable() 中:

use Filament\Forms\Components\Repeater;

Repeater::make('qualifications')
    ->relationship('qualifications')
    ->schema([
        // ...
    ])
    ->orderable('order_column')

网格布局

你可以使用 grid() 方法组织 Repeater 项目:

use Filament\Forms\Components\Repeater;

Repeater::make('members')
    ->schema([
        // ...
    ])
    ->grid(2)

该方法与 gridcolumns() 方法相似,接收相同的参数选项。让你可以在不同临界点自定义网格列数。

项目标签

你可以使用 itemLabel() 方法,为 Repeater 项目添加标签:

use Filament\Forms\Components\Repeater;
use Filament\Forms\Components\TextInput;

Repeater::make('members')
    ->schema([
        TextInput::make('name')
            ->lazy(),
    ])
    ->itemLabel(fn (array $state): ?string => $state['name'] ?? null),

如果你希望项目标签动态更新,那么使用 $state 获取的字段,应该是 reactive()lazy() 的。

使用 $get() 访问父级字段值

所有表单组件都可以使用 $get()$set() 获取其他字段的值。然而,在 Repeater 中使用可能会碰到异常。

这是因为默认情况下,$get()$set() 被限定在当前 repeater 项目中。也就是说,你可以在 repeater 项目中的其他字段交互,而不需要了解该表单属于哪一个 repeater 条目。

其结果是,当你不能与 repeater 字段进行互动时,会感到困惑。我们使用 ../ 语法来解决此问题 - $get('../../parent_field_name')

假设你的表单数据结构如下:

[
    'client_id' => 1,

    'repeater' => [
        'item1' => [
            'service_id' => 2,
        ],
    ],
]

你需要在 repeater 项目中检索 client_id 的值。

$get() 用于检索当前的 repeater 项, 因此 $get('client_id') 意味着 $get('repeater.item1.client_id')

你可以使用 ../ 切换到数据结构的上一级,因此 $get('../client_id') 相当于 $get('repeater.client_id')$get('../../client_id') 相当于 $get('client_id')

Builder

类似于 Repeater,Builder 组件让你可以以 JSON 数组的形式输出重复的表单组件。所有不同的是,Repeater 只定义了一个需要重复的表单的 schema,而 Builder 允许定义多个 schema 代码块,你可以以任何顺序进行排序。这有助于创建更高级的数组结构。

Builder 组件的主要用途,是使用预定义的代码块来搭建网页内容。下例在页面内容中为不同的元素定义了多个代码块。在你网站的前端,你可以使用 JSON 或者你需要的格式遍历每个代码块。

use Filament\Forms\Components\Builder;
use Filament\Forms\Components\FileUpload;
use Filament\Forms\Components\MarkdownEditor;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;

Builder::make('content')
    ->blocks([
        Builder\Block::make('heading')
            ->schema([
                TextInput::make('content')
                    ->label('Heading')
                    ->required(),
                Select::make('level')
                    ->options([
                        'h1' => 'Heading 1',
                        'h2' => 'Heading 2',
                        'h3' => 'Heading 3',
                        'h4' => 'Heading 4',
                        'h5' => 'Heading 5',
                        'h6' => 'Heading 6',
                    ])
                    ->required(),
            ]),
        Builder\Block::make('paragraph')
            ->schema([
                MarkdownEditor::make('content')
                    ->label('Paragraph')
                    ->required(),
            ]),
        Builder\Block::make('image')
            ->schema([
                FileUpload::make('url')
                    ->label('Image')
                    ->image()
                    ->required(),
                TextInput::make('alt')
                    ->label('Alt text')
                    ->required(),
            ]),
    ])

建议在数据库中以 JSON 方式保存 Builder 的数据。另外,如果使用的是 Eloquent,确保对字段进行 array 造型。

如上例所示,代码块被定义在组件的 blocks() 方法中。代码块(Block) 是 Builder\Block 对象,有一个唯一名称以及一个组件 schema:

use Filament\Forms\Components\Builder;
use Filament\Forms\Components\TextInput;

Builder::make('content')
    ->blocks([
        Builder\Block::make('heading')
            ->schema([
                TextInput::make('content')->required(),
                // ...
            ]),
        // ...
    ])

默认情况下,代码块的标签会基于其名称自动生成。要重写代码块标签,请使用 label() 方法。如果你想使用本地化翻译字符,以此自定义标签是个有效的方式:

use Filament\Forms\Components\Builder;

Builder\Block::make('heading')->label(__('blocks.heading'))

Block 也可以添加图标,显示在标签旁边。icon() 方法接收 Blade 图标组件作为参数:

use Filament\Forms\Components\Builder;

Builder\Block::make('heading')->icon('heroicon-o-bookmark')

你也可以使用 minItems()maxItems() 方法自定义可以创建的项目数量:

use Filament\Forms\Components\Builder;
use Filament\Forms\Components\TextInput;

Builder::make('content')
    ->blocks([
        // ...
    ])
    ->minItems(1)
    ->maxItems(10)

可折叠

可以使用 collapsible() 方法,在长表单中选择性隐藏内容:

use Filament\Forms\Components\Builder;

Builder::make('content')
    ->blocks([
        // ...
    ])
    ->collapsible()

可以默认折叠所有项目:

use Filament\Forms\Components\Builder;

Builder::make('content')
    ->blocks([
        // ...
    ])
    ->collapsed()

标签输入框

标签(Tag)输入组件让你可以和标签列表交互。

默认情况下,标签以 JOSN 方式保存:

use Filament\Forms\Components\TagsInput;

TagsInput::make('tags')

如果你使用 Eloquent 保存 JSON 标签,你应该在模型属性中添加 array casts

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    protected $casts = [
        'tags' => 'array',
    ];

    // ...
}

你也可以用分隔字符串保存 Tag 标签。要启用这种方法,在 separator() 方法传入分隔字符:

use Filament\Forms\Components\TagsInput;

TagsInput::make('tags')->separator(',')

标签输入框可以使用自动补全建议。要启用这个功能,在 suggestions() 方法中传入一个数组:

use Filament\Forms\Components\TagsInput;

TagsInput::make('tags')
    ->suggestions([
        'tailwindcss',
        'alpinejs',
        'laravel',
        'livewire',
    ])

Filament 也支持 spatie/laravel-tags。更多信息可查看插件文档

文本区

文本区(textarea)让你可以和多行字符串进行交互:

use Filament\Forms\Components\Textarea;

Textarea::make('description')

通过定义 rows()cols() 方法来调整文本区的大小:

use Filament\Forms\Components\Textarea;

Textarea::make('description')
    ->rows(10)
    ->cols(20)

你可以设置 minLength()maxLength() 方法限制字符串长度。这些方法同时添加了前端和后端验证器:

use Filament\Forms\Components\Textarea;

Textarea::make('description')
    ->minLength(50)
    ->maxLength(500)

键值对

键值对(key-value)字段让你可以与一维 JSON 对象进行交互:

use Filament\Forms\Components\KeyValue;

KeyValue::make('meta')

你可以使用 keyLable()valueLabel() 方法,自定义键值对字段的标签:

use Filament\Forms\Components\KeyValue;

KeyValue::make('meta')
    ->keyLabel('Property name')
    ->valueLabel('Property value')

你也可以禁止用户添加行,删除行,或者编辑行:

use Filament\Forms\Components\KeyValue;

KeyValue::make('meta')
    ->disableAddingRows()
    ->disableDeletingRows()
    ->disableEditingKeys()

你可以允许用户在表格中对行重新排序:

use Filament\Forms\Components\KeyValue;

KeyValue::make('meta')
    ->reorderable()

你也可以使用 keyPlaceholder()valuePlaceholder() 方法为键值对字段添加占位符:

use Filament\Forms\Components\KeyValue;

KeyValue::make('meta')
    ->keyPlaceholder('Property name')
    ->valuePlaceholder('Property value')

颜色选择器

颜色选择器(Color Picker)组件让你可以以一系列格式选择颜色。

默认情况下,组件使用 HEX(16 进制)格式:

use Filament\Forms\Components\ColorPicker;

ColorPicker::make('color')

另外,你可以使用不同格式:

use Filament\Forms\Components\ColorPicker;

ColorPicker::make('hsl_color')->hsl()
ColorPicker::make('rgb_color')->rgb()
ColorPicker::make('rgba_color')->rgba()

视图字段

除了创建自定义字段,你可以创造"视图(view)"字段,让你可以不需要创建另外的 PHP 类就可以创建自定义字段。

use Filament\Forms\Components\ViewField;

ViewField::make('notifications')->view('filament.forms.components.range-slider')

在你的视图内,你可以使用 Livewire 和 Alpine.js 与表单组件进行状态交互。

视图可以使用 $getStatePath() 闭包获取字段类的 Livewire 属性 path。你可以使用 wire:model 进行数据绑定,或者 $wire.entangle 与 Alpine.js 进行交互。

使用 Livewire's entangle 与 Alpine.js 共享 state:

<x-dynamic-component
    :component="$getFieldWrapperView()"
    :id="$getId()"
    :label="$getLabel()"
    :label-sr-only="$isLabelHidden()"
    :helper-text="$getHelperText()"
    :hint="$getHint()"
    :hint-action="$getHintAction()"
    :hint-color="$getHintColor()"
    :hint-icon="$getHintIcon()"
    :required="$isRequired()"
    :state-path="$getStatePath()"
>
    <div x-data="{ state: $wire.entangle('{{ $getStatePath() }}').defer }">
        <!-- Interact with the `state` property in Alpine.js -->
    </div>
</x-dynamic-component>

或者,你可以使用 wire:model 将其值绑定到 Livewire 属性:

<x-dynamic-component
    :component="$getFieldWrapperView()"
    :id="$getId()"
    :label="$getLabel()"
    :label-sr-only="$isLabelHidden()"
    :helper-text="$getHelperText()"
    :hint="$getHint()"
    :hint-action="$getHintAction()"
    :hint-color="$getHintColor()"
    :hint-icon="$getHintIcon()"
    :required="$isRequired()"
    :state-path="$getStatePath()"
>
    <input wire:model.defer="{{ $getStatePath() }}" />
</x-dynamic-component>

创建自定义字段

你也可以创建自定义的表单类和视图,用来在应用内复用,甚至向社区发布插件。

如果你只是需要创建一次性使用的简单自定义字段,你可以使用视图字段来渲染自定义模板文件。

要自定义表单字段类和视图,你可以使用以下命令:

php artisan make:form-field RangeSlider

该命令会创建如下字段类:

use Filament\Forms\Components\Field;

class RangeSlider extends Field
{
    protected string $view = 'filament.forms.components.range-slider';
}

在你的视图内,你可以使用 Livewire 和 Alpine.js 与表单组件进行状态交互。

视图可以使用 $getStatePath() 闭包获取字段类的 Livewire 属性 path。你可以使用 wire:model 进行数据绑定,或者 $wire.entangle 与 Alpine.js 进行交互:

<x-dynamic-component
    :component="$getFieldWrapperView()"
    :id="$getId()"
    :label="$getLabel()"
    :label-sr-only="$isLabelHidden()"
    :helper-text="$getHelperText()"
    :hint="$getHint()"
    :hint-action="$getHintAction()"
    :hint-color="$getHintColor()"
    :hint-icon="$getHintIcon()"
    :required="$isRequired()"
    :state-path="$getStatePath()"
>
    <div x-data="{ state: $wire.entangle('{{ $getStatePath() }}').defer }">
        <!-- Interact with the `state` property in Alpine.js -->
    </div>
</x-dynamic-component>
Edit on GitHub

Still need help? Join our Discord community or open a GitHub discussion

上一页
开始
下一页
布局