Use Action in custom ViewRecord page

hi there. sorry if this is a poor question, new to Filament and am sorely confused. I have a "ViewEvent" page I created that extends ViewRecord with a custom view and it has been working great as a Livewire component as far as I can tell. I'm using notifications without any issue as well. I see on the docs that using an Action on a Page is already set up for you and you shouldn't have to extend anything but when I try to use a CreateAction, nothing happens. No errors, nothing in console log. I looked at ViewRecord and what it extends and I see that it implements forms but did not find the action implementation, so I added it to myself like the docs say for a normal livewire component and I get:
Declaration of Filament\Actions\Concerns\InteractsWithActions::getMountedActionFormModel(): Illuminate\Database\Eloquent\Model|string|null must be compatible with Filament\Resources\Pages\ViewRecord::getMountedActionFormModel(): Illuminate\Database\Eloquent\Model
Declaration of Filament\Actions\Concerns\InteractsWithActions::getMountedActionFormModel(): Illuminate\Database\Eloquent\Model|string|null must be compatible with Filament\Resources\Pages\ViewRecord::getMountedActionFormModel(): Illuminate\Database\Eloquent\Model
the second I hit the page. i imagine im doing something wrong I'm just not sure what. I'm able to access my record, etc. with no issues on my page otherwise. i feel like im mistaken somewhere since the docs imply this should be ready to roll without me doing anything really.
46 Replies
jerry55551
jerry55551OP16mo ago
public function assignStaff()
{
return CreateAction::make()
->model(EventPositionAssignment::class)
->form([
Select::make('event_position_id')
->options($this->record->positions->pluck('name', 'id'))
->required()
->label('Position'),

Select::make('user_id')
->options(User::all()->pluck('name', 'id'))
]);
}
public function assignStaff()
{
return CreateAction::make()
->model(EventPositionAssignment::class)
->form([
Select::make('event_position_id')
->options($this->record->positions->pluck('name', 'id'))
->required()
->label('Position'),

Select::make('user_id')
->options(User::all()->pluck('name', 'id'))
]);
}
is my method for the action. I dd'd inside of it before the CreateAction and it fires just fine. also my view is wrapped in <x-filament-panels::page> – not sure if I need something else? not seeing anything when looking at the default panel views though 😩
Matthew
Matthew16mo ago
So if I understand correctly, you want a CreateAction inside a ViewPage? Also, is it a ViewPage of a resource or just filament page
jerry55551
jerry55551OP16mo ago
yeah unless there's a better way I could make it so someone with the right permissions can assign people to an "Event Position" while viewing an event. its a viewpage of a resource and the record works, etc. and has protected static string $resource = EventResource::class; $record works in my view, etc. havent had any issues and the template is a bit more custom further up so i did it all with a custom view so the Assign Staff is what im trying to get to pop the CreateAction for a modal pretty much allowing them to manually assign staff without them having an application
Matthew
Matthew16mo ago
Go to the View file
Matthew
Matthew16mo ago
No description
Matthew
Matthew16mo ago
and add create action
Matthew
Matthew16mo ago
Here
No description
Matthew
Matthew16mo ago
Can you share code pls?
jerry55551
jerry55551OP16mo ago
for which, the view?
Matthew
Matthew16mo ago
yes I see the problem I think Its the wrong CreateAction You have
use Filament\Actions\CreateAction;
use Filament\Actions\CreateAction;
You need:
use Actions\CreateAction:
use Actions\CreateAction:
jerry55551
jerry55551OP16mo ago
what would the full namespace be? if i just do Action\CreateAction it uses my current namespace which is namespace App\Filament\Resources\EventResource\Pages
jerry55551
jerry55551OP16mo ago
use Filament\Actions\CreateAction;
use Filament\Forms\Components\TextInput;

CreateAction::make()
->model(Post::class)
->form([
TextInput::make('title')
->required()
->maxLength(255),
// ...
])
use Filament\Actions\CreateAction;
use Filament\Forms\Components\TextInput;

CreateAction::make()
->model(Post::class)
->form([
TextInput::make('title')
->required()
->maxLength(255),
// ...
])
it shows this 😩
jerry55551
jerry55551OP16mo ago
and then it says https://filamentphp.com/docs/3.x/panels/pages#adding-actions-to-pages about pages already being wired up and ready to roll so i figured it was free game lol
jerry55551
jerry55551OP16mo ago
added <x-filament-actions::modals /> to my view just now as a sanity check but no change.
Matthew
Matthew16mo ago
Im not sure you need this. Since the ViewEvent is part of the resource
jerry55551
jerry55551OP16mo ago
yeah i didnt think i did, and yeah my view is wrapped in <x-filament-panels::page> just like the example at the bottom of the viewing-records page :/ im genuinely confused. ive been at it for a few days and haven't had a single hiccup til now lol it looks like i could do some of the stuff im doing on this page with custom info list layouts or idk do some fancier stuff than im doing now but to start i just want to get the basic modal popping in my component lol just bumped to 3.0.8 that just released just in case, that didn't fix it either. lol yeah idk im stumped lol gotta head off for a bit but if anyone has any ideas on this it'd be greatly appreciated. i really need it :/
Log1x
Log1x16mo ago
im having trouble with this too no idea
awcodes
awcodes16mo ago
I will admit I haven’t read the whole thread, but can I ask why you all are trying to shoe horn an edit record action into a view page which it is not design to edit a record. What is the advantage of sending a user with editing rights to a view page instead of an edit page?
Log1x
Log1x16mo ago
They mention their use-case here and I think it's pretty sane. I'm doing something similar. they have a view page for an "event" and want people who own the event to be able to manage "positions" while viewing the event. seems sane to do for UX without having to navigate away to edit plus considering Action's are implied as being able to be used literally anywhere (including standalone livewire components), why they wouldn't work under the condition of a ViewRecord makes no sense.
awcodes
awcodes16mo ago
So make the action a redirect to the edit url. It doesn’t have to be so complicated that the editing or the creation has to be reimplemented in an action.
Log1x
Log1x16mo ago
it would literally destroy the UX of my app (and theirs judging by the looks of things). i dont think this is some obscure thing to ask. the prebuilt-actions say on the docs they can be used literally anywhere including livewire components: https://filamentphp.com/docs/3.x/actions/prebuilt-actions/create
Log1x
Log1x16mo ago
why would having it on a ViewRecord suddenly be a big bad thing? if they have an event that has event positions and they want to quickly add someone to a position assignment with a modal (CreateAction) on their event view, why can't do they do that? especially if the "assignment" was small (e.g. a Position select and a User select), going to a whole new page for that would just seem awkward. and can't you just authorize it in ->before() or something on the Action? and otherwise hide it in the view for non-admins or people who don't own the event? im not really seeing the added complexity. the docs provide a way to handle everything needed for the action as far as i can see. authorizing it and handling all that stuff is up to me and im completely ok with that. idk i love the relation manager/general flow of everything as much as the next person, but this definitely makes sense to me and the docs imply it shouldn't be an issue. if i have to do my own modal and own thing to add this functionality with pure livewire, that's fine, i can do that. but the way actions made it sound on the docs, it seemed like i was going to be cruising full force being able to use 99% filament on the way even with the more custom requirements for the project by just using Actions inside of Pages with custom views like they are typical Livewire components. It 100% made sense for me and the docs implied it'd be good to go. Not sure if they are doing this, but another example would be: - Admins create events for Clients - Clients can View their event but can not Edit - Clients while Viewing their event can accept/decline Applications for Event Positions - Clients while Viewing their event can pop an Action to manually request or assign someone to a Event Position - Clients can not do anything else. idk theres a ton of example scenarios i could come up with for wanting this lol but again no problem doing it custom, it'd just be awesome if i could use the Actions because they are nice 🙂 having to bring in a custom modal component and deal with that mess isn't ideal if avoidable.
awcodes
awcodes16mo ago
You can certainly use custom actions, but it seems to me that there might be a misunderstanding and attempted abuse of the prebuilt actions, with expectations of them to work out side their intended behavior.
Log1x
Log1x16mo ago
public function assignStaff()
{
return CreateAction::make()
->model(EventPositionAssignment::class)
->form([
Select::make('event_position_id')
->options($this->record->positions->pluck('name', 'id'))
->required()
->label('Position'),

Select::make('user_id')
->options(User::all()->pluck('name', 'id'))
]);
}
public function assignStaff()
{
return CreateAction::make()
->model(EventPositionAssignment::class)
->form([
Select::make('event_position_id')
->options($this->record->positions->pluck('name', 'id'))
->required()
->label('Position'),

Select::make('user_id')
->options(User::all()->pluck('name', 'id'))
]);
}
okay so having something simple like this in a wire:click is not ok? everything on the docs implies it is. (the above example is missing validation and other stuff, this is just a barebones example from them above) hmm looking at the livewire component actions docs, maybe you have to straight up echo assignStaff?
awcodes
awcodes16mo ago
Why not use an Action instead of overriding CreateAction? Pre built actions have a specific intent and goal/outcome. Just use an Action and do what ever you need to do with it.
Log1x
Log1x16mo ago
instead of a wire:click hmm ok i see. let me mess with it. i think if im understanding, the CreateAction is supposed to return as a button or something? which would make sense why it doesn't work in a wire:click lol lemme add some of the functionality back into my own app to play with but yeah that would make sense and doing a custom action or just using the button its self might be ideal
awcodes
awcodes16mo ago
CreateAction is a preconfigured action the in the right context will either take you to a CreateResource page or open a model to create a record based on a simple resource.
awcodes
awcodes16mo ago
You’re trying to use that outside of its context so it doesn’t have access to what you’re expecting it to have access to.
Log1x
Log1x16mo ago
yeah makes sense
awcodes
awcodes16mo ago
But you can achieve what you want by just defining an Action.
Log1x
Log1x16mo ago
getting:
Filament\Resources\Pages\ViewRecord::cacheInfolist(): Argument #2 ($infolist) must be of type Filament\Infolists\Infolist, Filament\Actions\Action given
Filament\Resources\Pages\ViewRecord::cacheInfolist(): Argument #2 ($infolist) must be of type Filament\Infolists\Infolist, Filament\Actions\Action given
when trying to echo out my action in my view whether its a Action or desperate check with CreateAction, they all give the same error about cacheInfolist for some reason. im not echoing or using info lists on my view at the moment so im not entirely sure in this scenario. ah echoing it as {{ $this->testAction() }} instead of {{ $this->testAction }} makes it render the button – but nothing happens when I click it even after adding <x-filament-actions::modals /> (which I think is already on the page layout). still messing with it.
awcodes
awcodes16mo ago
View pages use info lists by default. It that helps to debug.
Log1x
Log1x16mo ago
hmm. when I click my action I see a network request go out and it returns the modal html and everything looks great but no modal appears. i added <x-filament-actions::modals /> to my view but nothing changes. my view its self is wrapped in <x-filament-panels::page> and as far as i can tell nothing touches the DOM i dont think im seeing any script differences between the view pages and pages with a relation manager with modals x_x i dont know why it wouldn't be firing. ok cool so adding it as a header action worked, but echoing it as a standalone button inside of my custom view does not if i can figure out that im golden
awcodes
awcodes16mo ago
You have keep in mind where your action psychically is. In the headers it will be a Filament/Actions/Action, in a table context it will be a Filament/Tables/Actions/Action. I might not have those namespace right. But hopefully you get might point. They can indeed be used anywhere but the context to what you are trying to do does matter.
Log1x
Log1x16mo ago
right now im trying to just do a Filament\Actions\Action inside of a method that then gets echo'd in my view with {{ $this->testAction() }} – the button gets rendered but clicking it only sends a network request, no modal appears.
awcodes
awcodes16mo ago
It shouldn’t be a method when trying to render it. So $this->testAction No parentheses.
Log1x
Log1x16mo ago
if i dont add () it gets rendered as an info list and an exception gets thrown
awcodes
awcodes16mo ago
Also the name of the action matters
Log1x
Log1x16mo ago
i saw the docs had appended "Action" to the method names so mine is just called testAction I get Filament\Resources\Pages\ViewRecord::cacheInfolist(): Argument #2 ($infolist) must be of type Filament\Infolists\Infolist, string given if I try to render it without parenthesis
awcodes
awcodes16mo ago
Ok. I’d need to see the code. It’s hard to explain. But you’re on the right track. I’m just not sure what part of what your trying to do is considered the livewire component.
Log1x
Log1x16mo ago
well in this case, nothing is the related to the livewire component its self. i just want to echo out the action button in a certain place in my record view. all of the livewire-specific stuff works as intended. otherwise I think it being a ViewRecord is getting in the way of me echoing out the action like its supposed too because it forces the infolist stuff on it Here's a barebones example which should technically just work:
<x-filament-panels::page>
<div>
<div>Test</div>
<div>{{ $this->testAction() }}</div>
</div>
</x-filament-panels::page>
<x-filament-panels::page>
<div>
<div>Test</div>
<div>{{ $this->testAction() }}</div>
</div>
</x-filament-panels::page>
<?php

namespace App\Filament\Resources\EventResource\Pages;

use App\Filament\Resources\TestResource;
use Filament\Actions\Action;
use Filament\Resources\Pages\ViewRecord;
use Filament\Forms\Components\Select;
use App\Models\User;

class ViewTest extends ViewRecord
{
/**
* The resource class.
*/
protected static string $resource = TestResource::class;

/**
* The page view.
*/
protected static string $view = 'filament.pages.view-test';

/**
* The test action.
*
* @return Action
*/
public function testAction()
{
return Action::make('assignTest')
->fillForm([
'test_id' => $this->record->id,
])
->form([
Select::make('user_id')
->options(User::all()->pluck('name', 'id'))
])
->action(function (array $data): void {
dd($data);
});
}
}
<?php

namespace App\Filament\Resources\EventResource\Pages;

use App\Filament\Resources\TestResource;
use Filament\Actions\Action;
use Filament\Resources\Pages\ViewRecord;
use Filament\Forms\Components\Select;
use App\Models\User;

class ViewTest extends ViewRecord
{
/**
* The resource class.
*/
protected static string $resource = TestResource::class;

/**
* The page view.
*/
protected static string $view = 'filament.pages.view-test';

/**
* The test action.
*
* @return Action
*/
public function testAction()
{
return Action::make('assignTest')
->fillForm([
'test_id' => $this->record->id,
])
->form([
Select::make('user_id')
->options(User::all()->pluck('name', 'id'))
])
->action(function (array $data): void {
dd($data);
});
}
}
oh wow i got it i think. if you name testAction to assignTestAction instead and then yeah, you can just call it with parenthesis while on a viewrecord. you're right on the naming stuff.
Arnaud
Arnaud16mo ago
Thanks should be mentionned in the doc
daregu
daregu4mo ago
Finally I found it! thnx @Log1x. Maybe it can be a PR.
Want results from more Discord servers?
Add your server