Sharing form() Resources ?

I was wondering if I could load another resource's $form into the --simple modal of a different resource? Use case: I can quickly access resource views quickly such as comment threads (from dash) related to other models...rather then having to go to that resource table, find the record with comments, click through...etc.. Having a table of comments is not very useful, but clicking through to the record where all of the comments exist on the related model is more useful I believe. From my attempts the trick seems to be associating the model record with the form, while inside of another resource. Not sure how to do this. An example from my code is:
//IllustrationSketchesRelationManager::form holds the form fields AND Model-Record I'd like to reuse.

public static function form(Form $form): Form
{
return IllustrationSketchesRelationManager::form(new \Filament\Resources\Form();
}
//IllustrationSketchesRelationManager::form holds the form fields AND Model-Record I'd like to reuse.

public static function form(Form $form): Form
{
return IllustrationSketchesRelationManager::form(new \Filament\Resources\Form();
}
I'm referencing the form above, but it obviously has no awareness of the correct model. Are there any methods that allow passing in the correct model/record? OR maybe I'm thinking about this incorrectly, or it's quite possible that this is not even possible with filament.
25 Replies
Dan Harrin
Dan Harrin2y ago
its simpler than you think
public static function form(Form $form): Form
{
return ClassNameHere::form($form);
}
public static function form(Form $form): Form
{
return ClassNameHere::form($form);
}
bionary
bionaryOP2y ago
thank you by not quite @Dan Harrin Still getting error: Filament\Forms\Components\SpatieMediaLibraryFileUpload::Filament\Forms\Components\{closure}(): Argument #2 ($record) must be of type Spatie\MediaLibrary\HasMedia, App\Models\Comment given, called in I am currently inside CommentResource, but need to pass the record from another Model/Record to this form. That' my issue. When I dd() on any of the components I can see that it is loading the Model/Record: Comment, when what I need is the Model/Record: IllustrationSketch hope I'm being clear btw: I am going into one of the form/view items and adding <?php dd($this->cachedMountedTableActionRecord); ?> and it outputs props for App\Models\Comment Not sure if $this->cachedMountedTableActionRecord is legit way, but that's all I know from inspecting dd()'s and source diving as best as I can. I can also dump out access to the model I want via php in a view like: $this->cachedMountedTableActionRecord->commentable That's the model I'm trying to load into the form, but not sure how to from inside the form() method? I believe what I'm looking for would be something like this:
public static function form(Form $form): Form
{
return ClassNameHere::form($this->record->commentable);
}
public static function form(Form $form): Form
{
return ClassNameHere::form($this->record->commentable);
}
But that obviously wont work because there is no $this state inside a static method hmmmm I'm out of ideas
Dan Harrin
Dan Harrin2y ago
sounds like you just need a HasMedia interface on your Comment model because the form schema contains a spatie file upload
bionary
bionaryOP2y ago
I did add that just to see. That error indeed goes away, but the wrong model is loaded. $form want's to load the \models\Comment record when I need it to load \models\IllustrationSketch I've spent the last hour searching discord and the only way it seems possible to even grab the $record whilist in the form() method is via some chained methods inside the form, which is a bit of a catch 22 here for me
Dan Harrin
Dan Harrin2y ago
i think im misunderstanding what youre trying to do what i think you're trying to do is use the exact same schema for both forms im not correct am i
awcodes
awcodes2y ago
Yea. Something seems backwards about this. Been trying wrap my brain around it.
bionary
bionaryOP2y ago
I have a knack for being confusing...I apologize Let me take some screen shots and hopefully I will present my case clearer
awcodes
awcodes2y ago
Isn’t commentable a polymorphic relation? You should be able to pull the relationship of it and use that to programmatically get the form for the related model.
bionary
bionaryOP2y ago
Yes, I can no problem in regular php/laravel ... ->commentable but I dont think I can access the model ahead of the $form so that's where things get stuck
bionary
bionaryOP2y ago
bionary
bionaryOP2y ago
I realize I could use URL to jump to that particular view, but I would really, really like to open things in a modal. I'm trying to provide a way for users to quickly see new comments and comment back. So the Comment model is polymorphic.
awcodes
awcodes2y ago
Yea. Filament is still laravel. That’s kinda the beauty of it.
bionary
bionaryOP2y ago
@awcodes If I could do this I would be golden:
public static function form(Form $form): Form
{
return IllustrationSketchesRelationManager::form($this->record->commentable);
}
public static function form(Form $form): Form
{
return IllustrationSketchesRelationManager::form($this->record->commentable);
}
but I cannot inside a static method
awcodes
awcodes2y ago
So, this is hard to describe typing it out.
bionary
bionaryOP2y ago
ha ha indeed welcome to my life
awcodes
awcodes2y ago
You have the commentable. So, in pseudo code:
{Commentable->relatedClass}Resource::getFormSchema()
{Commentable->relatedClass}Resource::getFormSchema()
Something along those lines. Or define the schema on the model and pull it from there in the appropriate resources. You might actually need a custom action for this though that you can assign to the row click.
bionary
bionaryOP2y ago
hmmm okay, maybe forget about the default view/edit and load the $form into a modal via Action.
awcodes
awcodes2y ago
Possibly. I’m kinda guessing here. Lol.
bionary
bionaryOP2y ago
The problem is still accessing the record, while inside a static method. I'm trying to set a property...let's see (in the middle right now)
awcodes
awcodes2y ago
My brain says it’s definitively possible. Just not sure how to convey it. Static doesn’t matter, the record in your case is the comment, not the related model. But since it’s polymorphic you should be able to use the related record to get the class name and use that to retrieve the form schema. So, on the Post model, for example, have a method that returns the form schema as an array. Then you can call that off the comments relationship to the post model. And still also use it on the PostResource’s form method. If that makes sense. I’m probably not explaining it well.
bionary
bionaryOP2y ago
let me digest this and attempt Okay, but how would you access the record here:
public static function form(Form $form): Form
{
???
}
public static function form(Form $form): Form
{
???
}
awcodes
awcodes2y ago
Basically, the post model has a method called getFormSchema() that returns an array of all the form fields for that model. Then you can call comment->relatedModel->getFormSchema() inside the form method anywhere you need to use it.
return $record->relatedModel->getFormSchema();
return $record->relatedModel->getFormSchema();
You don’t have to define the form schema in the resource you can define it on the model and just return it in the form method on the resource.
bionary
bionaryOP2y ago
interesting I created an Action instead of trying to load the view with the form() method. My Action looks like this:
Tables\Actions\Action::make('view')->label('View & Comment')
->form(fn($record) => $record->commentable->getFormSchema())
->action(fn()=>null)
Tables\Actions\Action::make('view')->label('View & Comment')
->form(fn($record) => $record->commentable->getFormSchema())
->action(fn()=>null)
In the model I'm referring to my public method looks like this:
public function getFormSchema()
{
//works
return [
\Filament\Forms\Components\TextInput::make('inp')
];

//does not work
$form = new \Filament\Resources\Form;
return $form->schema([
\Filament\Forms\Components\TextInput::make('inp')
]);
}
public function getFormSchema()
{
//works
return [
\Filament\Forms\Components\TextInput::make('inp')
];

//does not work
$form = new \Filament\Resources\Form;
return $form->schema([
\Filament\Forms\Components\TextInput::make('inp')
]);
}
Just testing a simple input. I immediately see a problem. The Action::form method is looking for an array, not the Schema? That means all the fancy Groups, Sections, etc... cannot be included. Once again, maybe I am going about your suggestion wrong. Adding an Action is the only way I can think of access $record or maybe I just need to include them all inside the array? (thinking out loud) ..let me see okay, now I'm getting somewhere I can pack all the styling schema stuff into that array! This works:
return [
\Filament\Forms\Components\Group::make([
\Filament\Forms\Components\TextInput::make('inp'),
])
];
return [
\Filament\Forms\Components\Group::make([
\Filament\Forms\Components\TextInput::make('inp'),
])
];
nice Gonna sleep on this and hit it again tomorrow. Thanks guys Here's what I figured out so far:
//IllustrationSketch (parent model of \Comment.php)
public function getFormSchema()
{
return [
\Filament\Forms\Components\Group::make([
\Filament\Forms\Components\TextInput::make('comment'),
])
];
}

//CommentResource
public static function table(Table $table): Table
{
return $table
->columns([
TextColumn::make('commenter.name'),
TextColumn::make('body')->limit(50)
])
->filters([])
->actions([
Tables\Actions\EditAction::make(),
Tables\Actions\DeleteAction::make(),
Tables\Actions\Action::make('view')->label('View & Comment')
->mountUsing(fn (Forms\ComponentContainer $form, Comment $record) => $form->fill([
'comment' => $record->commentable->comment,
]))
->form(fn($record) => $record->commentable->getFormSchema())
->action(function (Comment $record, array $data): void {
//Manually save....
dd($data);
})
])
->bulkActions([]);
}
//IllustrationSketch (parent model of \Comment.php)
public function getFormSchema()
{
return [
\Filament\Forms\Components\Group::make([
\Filament\Forms\Components\TextInput::make('comment'),
])
];
}

//CommentResource
public static function table(Table $table): Table
{
return $table
->columns([
TextColumn::make('commenter.name'),
TextColumn::make('body')->limit(50)
])
->filters([])
->actions([
Tables\Actions\EditAction::make(),
Tables\Actions\DeleteAction::make(),
Tables\Actions\Action::make('view')->label('View & Comment')
->mountUsing(fn (Forms\ComponentContainer $form, Comment $record) => $form->fill([
'comment' => $record->commentable->comment,
]))
->form(fn($record) => $record->commentable->getFormSchema())
->action(function (Comment $record, array $data): void {
//Manually save....
dd($data);
})
])
->bulkActions([]);
}
Yes this is starting to work, but things are getting quite gross IMHO. Because there is no way to "set" the parent record as the focused record while in a child resource, I have to keep referring to the parent via the child record . As a result, I have to manually prepare the form and manually perform the save. No big deal if I had a couple of text inputs, but of course I don't 😉 I'm using some more complicated fields such as: SpatieMediaLibraryFileUpload, etc. <sigh> This is making me rethink my whole approach here. ... ... Let me ask some smart people this a different way: If you had a standard polymorphic relationship ( Posts|Videos => Comments) just like in Laravel docs:
bionary
bionaryOP2y ago
Laravel - The PHP Framework For Web Artisans
Laravel is a PHP web application framework with expressive, elegant syntax. We’ve already laid the foundation — freeing you to create without sweating the small things.
bionary
bionaryOP2y ago
Could you? Would you be able to have an Unread Comments page/table that listed all unread comments? And when clicking on an unread comment row in the table you would be presented NOT with the comment record but the Parent view/edit view that owns the Comment. This way you can read and respond to the whole comment thread.
As a result, clicking on Comment opens modal to Video record, clicking on Comment opens modal to Post, etc....
Want results from more Discord servers?
Add your server