有时候,单一的属性信息不足以在下拉列表选项中获取正确的记录。当然,你可以使用访问器(accessor)联结属性,不过这样可能不是很美观。假如我们需要展示图片呢?或许我们需要一点HTML。
由于 Filament 使用了 Choice.js
, 我们可以在每个下拉选项中渲染HTML。你只需在定义下拉列表字段时,使用 allowHtml()
方法就可以开启这一功能。
以下是带有头像的用户下拉列表的通用示例:
Select::make('user_id') ->label('User') ->allowHtml() // Apply the new modifier to enable HTML in the options - it's disabled by default ->searchable() // Don't forget to make it searchable otherwise there is no choices.js magic! ->getSearchResultsUsing(function (string $search) { $users = User::where('name', 'like', "%{$search}%")->limit(50)->get(); return $users->mapWithKeys(function ($user) { return [$user->getKey() => static::getCleanOptionString($user)]; })->toArray(); }) ->getOptionLabelUsing(function ($value): string { $user = User::find($value); return static::getCleanOptionString($user); })
->getSearchResultsUsing() - 返回搜索结果的键值对。键(key)为模型(用户)ID, 值为HTML字符串。
->getOptionLabelUsing() - 返回 HTML 字符串。
To keep it DRY I've added a static method to the resource to return the view.
public static function getCleanOptionString(Model $model): string{ return Purify::clean( view('filament.components.select-user-result') ->with('name', $model?->name) ->with('email', $model?->email) ->with('image', $model?->image) ->render() );}
注意:启用
allowHtml()
可能会有XSS攻击风险。请净化HTML字符串以保证安全!
最后,为视图创建 blade 模板文件
<div class="flex rounded-md relative"> <div class="flex"> <div class="px-2 py-3"> <div class="h-10 w-10"> <img src="{{ url('/storage/'.$image.'') }}" alt="{{ $name }}" role="img" class="h-full w-full rounded-full overflow-hidden shadow object-cover" /> </div> </div> <div class="flex flex-col justify-center pl-3 py-2"> <p class="text-sm font-bold pb-1">{{ $name }}</p> <div class="flex flex-col items-start"> <p class="text-xs leading-5">{{ $email }}</p> </div> </div> </div></div>