Reuse categories, tags (or any other morph many relationship) form fields, table columns, actions on many resources
If you got any morphs many model, eg. tags or categories, which you want to use on many resources, but don't want to repeat yourself, you can do as follows.
Trick shows how to:
So here is the meat:
create_tags_table.php:
Schema::create('tags', function (Blueprint $table) { $table->id(); $table->string('name', 50); $table->timestamps();});
create_taggables_table.php.php:
Schema::create('taggables', function (Blueprint $table) { $table->foreignId('tag_id'); $table->morphs('taggable');});
YourTaggableModel.php:
public function tags(){ return $this->morphToMany(Tag::class, 'taggable');}
MyResource.php:
use App\Filament\Resources\Traits\HasTags; class MyResource extends Resource{ use HasTags; public static function form(Form $form): Form { return $form->schema([ //...other fields self::formTagsField() ->columnSpan(['md' => 2, 'lg' => 3]), //you can add of course extra settings which you need in given resource ])->columns(['md' => 2, 'lg' => 3]); } public static function table(Table $table): Table { return $table ->columns([ //...other columns self::tagsColumn(), ]) ->bulkActions([ //...other bulk actions self::changeTagsAction(), ]); }
HasTags.php:
namespace App\Filament\Resources\Traits; use App\Models\Tag;use Illuminate\Support\Collection;use Filament\Forms\Components\Grid;use Filament\Forms\Components\Select;use Filament\Tables\Actions\BulkAction;use Filament\Tables\Columns\TagsColumn;use Filament\Forms\Components\TextInput; trait HasTags{ public static function formTagsField() : Select { return self::tagsField() ->relationship('tags', 'name'); } public static function tagsField() : Select { return Select::make('tags') ->options(Tag::pluck('name', 'id')) ->multiple() ->searchable() ->preload() ->createOptionForm([ TextInput::make('name') ->lazy() ->afterStateUpdated(fn ($set, $state) => $set('name', ucfirst($state))) ->required(), ]); } public static function changeTagsAction() : BulkAction { return BulkAction::make('change_tags') ->action(function (Collection $records, array $data): void { foreach ($records as $record) { $record->tags()->{$data['action']}($data['tags']); } }) ->form([ Grid::make() ->schema([ Select::make('action') ->label('For selected records') ->options([ 'attach' => 'add', 'detach' => 'remove', 'sync' => 'overwrite', ]) ->default('sync') ->required(), self::tagsField(), ])->columns(2) ]); } public static function tagsColumn() : TagsColumn { return TagsColumn::make('tags.name') ->limit(3); }}
No comments yet…