Jo
Jo
FFilament
Created by Jo on 4/17/2024 in #❓┊help
Testing a Livewire component that is has been added to an Infolist
I'f like to know how to test a Livewire component that has been added to an Infolist. I'm calling a Livewire component on an Infolist like this:
->schema([
Livewire::make(ManageJobGrade::class)
])
->schema([
Livewire::make(ManageJobGrade::class)
])
The Livewire component itself (used example from the Filament docs)
class ManageJobGrade extends Component implements HasForms, HasActions
{
use InteractsWithActions;
use InteractsWithForms;

public Job $job;

public function deleteAction(): Action
{
return Action::make('delete')
->requiresConfirmation()
->action(fn () => $this->job->delete());
}
}
class ManageJobGrade extends Component implements HasForms, HasActions
{
use InteractsWithActions;
use InteractsWithForms;

public Job $job;

public function deleteAction(): Action
{
return Action::make('delete')
->requiresConfirmation()
->action(fn () => $this->job->delete());
}
}
Now the test which is not working:
it('can delete jobs', function () {
$job = Job::factory()->create();

livewire(ViewJob::class, [
'job' => $job,
])
->mountAction('delete')
->assertActionExists('delete');
});
it('can delete jobs', function () {
$job = Job::factory()->create();

livewire(ViewJob::class, [
'job' => $job,
])
->mountAction('delete')
->assertActionExists('delete');
});
I know that usually on the Infolist we use mountInfolistAction() and not mountAction() but I saw in the HTML generated by the Livewire action that it's using just mountAction() and, besides, mountInfolistAction() didn't work. I also tried to do livewire(ManageJobGrade::class ... instead but then it literally passes every time, even when I put nonsense IDs in there.
14 replies
FFilament
Created by Jo on 4/16/2024 in #❓┊help
Learning Livewire to make custom components in Filament
Hi everyone, just looking for a bit of advice/opinions.... if I want to learn Livewire for the purpose of building custom components in Filament, are the official docs and paid screencasts the best way to go, or is there a better path for someone learning Livewire for the specific purpose of using it in Filament?
5 replies
FFilament
Created by Jo on 4/9/2024 in #❓┊help
Testing actions defined within extraModalFooterActions()
When using Pest for testing, is there a way to test the actions defined within extraModalFooterActions() ? I've tried the obvious things like mounting / calling the action which calls the modal first and even dot notation but nothing seems to be working. Basic example:
Action::make('action1')
->requiresConfirmation()
->extraModalFooterActions(fn (Action $action): array => [
$action->make('action2'),
]);
Action::make('action1')
->requiresConfirmation()
->extraModalFooterActions(fn (Action $action): array => [
$action->make('action2'),
]);
This test passes:
livewire(ViewPost::class, [
'record' => $this->record->getRouteKey(),
])
->mountInfolistAction('component', 'action1')
->assertInfolistActionExists('component', 'action1');
livewire(ViewPost::class, [
'record' => $this->record->getRouteKey(),
])
->mountInfolistAction('component', 'action1')
->assertInfolistActionExists('component', 'action1');
This fails:
livewire(ViewPost::class, [
'record' => $this->record->getRouteKey(),
])
->mountInfolistAction('component', 'action2')
->assertInfolistActionExists('component', 'action2');
livewire(ViewPost::class, [
'record' => $this->record->getRouteKey(),
])
->mountInfolistAction('component', 'action2')
->assertInfolistActionExists('component', 'action2');
Failed asserting that a infolist action with name [action2] is registered to [component] on the [App\Filament\Resources\PostResource\Pages\ViewPost] component.
Failed asserting that null is an instance of class Filament\Infolists\Components\Actions\Action.
Failed asserting that a infolist action with name [action2] is registered to [component] on the [App\Filament\Resources\PostResource\Pages\ViewPost] component.
Failed asserting that null is an instance of class Filament\Infolists\Components\Actions\Action.
I just want to be able to do a similar test for action2 as I can do for action1
15 replies
FFilament
Created by Jo on 3/22/2024 in #❓┊help
Testing relation managers
I have followed the info at https://filamentphp.com/docs/3.x/panels/resources/relation-managers#conditionally-showing-relation-managers to conditionally show a relation manager. However, I am facing a problem where testing always passes even when the relation manager is not rendered. As an extreme example, consider this code on the relation manager:
public static function canViewForRecord(Model $ownerRecord, string $pageClass): bool
{
return false;
}
public static function canViewForRecord(Model $ownerRecord, string $pageClass): bool
{
return false;
}
But this test passes:
use App\Filament\Resources\CategoryResource\Pages\EditCategory;
use function Pest\Livewire\livewire;

it('can render relation manager', function () {
$category = Category::factory()
->has(Post::factory()->count(10))
->create();

livewire(CategoryResource\RelationManagers\PostsRelationManager::class, [
'ownerRecord' => $category,
'pageClass' => EditCategory::class,
])
->assertSuccessful();
});
use App\Filament\Resources\CategoryResource\Pages\EditCategory;
use function Pest\Livewire\livewire;

it('can render relation manager', function () {
$category = Category::factory()
->has(Post::factory()->count(10))
->create();

livewire(CategoryResource\RelationManagers\PostsRelationManager::class, [
'ownerRecord' => $category,
'pageClass' => EditCategory::class,
])
->assertSuccessful();
});
In fact, to be even more extreme, I went into the CategoryResource class and removed the getRelations() function entirely so now I definitely don't have any relation manager displaying but that test is still passing. The only way I can get the test to fail is by deleting the PostsRelationManager entirely.
3 replies
FFilament
Created by Jo on 2/29/2024 in #❓┊help
assertRedirect to a URL with an ID when testing
Here's my Pest code which I write by looking at both the FilamentPHP and Livewire testing docs:
it('redirects to view when post created', function () {
livewire(CreatePost::class)
->fillForm([
'title' => 'Test title'
])
->call('create')
->assertRedirect(ViewPost::class);
});
it('redirects to view when post created', function () {
livewire(CreatePost::class)
->fillForm([
'title' => 'Test title'
])
->call('create')
->assertRedirect(ViewPost::class);
});
This fails saying, Missing required parameter for [Route: filament.admin.resources.posts.view] [URI: admin/posts/{record}] [Missing parameter: record] There doesn't seem to be a way to pass a param to this, so I changed it slightly:
->assertRedirect(route(
'filament.admin.resources.posts.view',
['record' => 16]
));
->assertRedirect(route(
'filament.admin.resources.posts.view',
['record' => 16]
));
Ok, that works. But obviously I'm hardcoding the ID. How am I supposed to get the ID when filling a form like this so that I can assert that it redirected to the correct route dynamically?
6 replies
FFilament
Created by Jo on 2/21/2024 in #❓┊help
Quick way to translate modal "Cancel" button?
Is there a quick way to translate a single button (the "Cancel" button that appears in form modals) or do I need to follow the procedure as if I was going to translate the entire framework?
5 replies
FFilament
Created by Jo on 2/16/2024 in #❓┊help
Displaying a Modal dialogue in an action instead of a Notification
Here's a simplified version of the code I've written to deduct credits from a user. Is there a straightforward way for the second notification (which is fired on InsufficientCreditsException) to be a modal dialogue instead of a notification? It's all working fine, but the users don't always notice when there's a notification so I want to change it to something a bit more "in your face" which forces the user to read and click a button to dismiss it before they can use the page again.
Action::make('action')
->label("Activate ad")
->action(function (DeductCreditAction $deductCredits) {
try {
$deductCredits(10);
Notification::make()
->title('Sufficient credits. Job active.')
->success()
->send();
} catch (InsufficientCreditsException $e) {
Notification::make()
->title('Sorry, insufficient credits')
->danger()
->send();
}
});
Action::make('action')
->label("Activate ad")
->action(function (DeductCreditAction $deductCredits) {
try {
$deductCredits(10);
Notification::make()
->title('Sufficient credits. Job active.')
->success()
->send();
} catch (InsufficientCreditsException $e) {
Notification::make()
->title('Sorry, insufficient credits')
->danger()
->send();
}
});
2 replies
FFilament
Created by Jo on 1/30/2024 in #❓┊help
Confirmation modal for actions other than delete?
Consider a situation where users of our panel have to "spend" a point/credit in order to create a new post. In this case, I can modify the example from the docs for a delete confirmation to be like this:
Action::make('create')
->action(fn (Post $record) => $record->create())
->requiresConfirmation()
Action::make('create')
->action(fn (Post $record) => $record->create())
->requiresConfirmation()
The problem with this, though, is that the confirmation modal appears before form validation has happened. I'd like to switch this around so that the form validation happens first and then the confirmation modal only first if the form passes validation.
2 replies
FFilament
Created by Jo on 1/22/2024 in #❓┊help
Combining filter, search and sorting into one row... possible?
No description
1 replies
FFilament
Created by Jo on 9/28/2023 in #❓┊help
Giving end-users access to a Filament panel
The new Filament 3 ability to create multiple panels makes me think that in some cases it might make more sense to let end-users of a website log into Filament to perform certain tasks. But I'm wondering whether there are reasons to avoid this? Consider, for example, a jobs board. The front end shows job ads, but instead of spending time making a bunch of frontend forms/tables to allow recruiters to post new job ads, and job seekers to apply for ads, you could just make 2 separate panels in Filament (ie: separate from the admin panel) and with a few permissions and filtering so that the recruiter only sees the job ads that belong to them, the recruiter could literally log into Filament to post and manage their ads. And then another panel could be made for job seekers to allow them to apply for jobs and otherwise manage their job applications. I suppose traditional thinking would be that only website owners/administrators should have access to the admin panel. But now that we can make multiple admin panels within Filament with different permissions only showing a subset of data, is there a reason NOT to do what I've described above?
4 replies
FFilament
Created by Jo on 3/14/2023 in #❓┊help
Having a relation manager under the edit form in a modal of a relation manager
I have a model which is called ServicePeriod which hasMany of another model called Slot. I have set up the relation manager successfully, so if I go to the edit screen of ServicePeriodI can see all of the related Slot records in a list with edit and delete buttons, and I can click on them to get an edit form which appears in a modal. All good so far. But each Slot also hasMany of another model called Sector and I want a list of all of the Sector records which are related to the Slot record to be displayed under the Slot edit form within the modal. Preferably I would like this to be the same style as the relation manager. I've obviously set up the getRelations() inside the SlotResource properly, but it isn't automatically showing under the edit form in the modal as it would do on a normal resource page. Is this possible, or am I going beyond what it's supposed to do?
6 replies