Assigning actions to buttons correctly

I have created a custom view for my page and rather than using the default header actions, I want to use my own buttons and pass the correct method to each button. Here is my widget class so far:
<?php

namespace App\Filament\Resources\ContactResource\Widgets;

use Filament\Actions;
use Filament\Widgets\Widget;
use Illuminate\Database\Eloquent\Model;

class ContactOverview extends Widget
{
protected static string $view = 'filament.resources.contact-resource.widgets.contact-overview';

public ?Model $record = null;

public function getIsSoftDeleted(): bool
{
return $this->record['deleted_at'] !== null;
}

public function edit(): void
{
Actions\EditAction::make();
}

public function delete(): void
{
Actions\DeleteAction::make();
}

public function forceDelete(): void
{
Actions\ForceDeleteAction::make();
}

public function restore(): void
{
Actions\RestoreAction::make();
}
}
<?php

namespace App\Filament\Resources\ContactResource\Widgets;

use Filament\Actions;
use Filament\Widgets\Widget;
use Illuminate\Database\Eloquent\Model;

class ContactOverview extends Widget
{
protected static string $view = 'filament.resources.contact-resource.widgets.contact-overview';

public ?Model $record = null;

public function getIsSoftDeleted(): bool
{
return $this->record['deleted_at'] !== null;
}

public function edit(): void
{
Actions\EditAction::make();
}

public function delete(): void
{
Actions\DeleteAction::make();
}

public function forceDelete(): void
{
Actions\ForceDeleteAction::make();
}

public function restore(): void
{
Actions\RestoreAction::make();
}
}
And here is the markup for my buttons:
<x-slot name="headerEnd">
<div class="flex flex-col space-y-2 md:flex-row md:space-y-0 md:space-x-2">
<x-filament::button wire:click="edit" class="w-28">
Edit
</x-filament::button>

@if(!$this->getIsSoftDeleted())
<x-filament::button wire:click="delete" color="danger" class="w-28">
Delete
</x-filament::button>
@endif

@if($this->getIsSoftDeleted())
<x-filament::button wire:click="forceDelete" color="danger" class="w-28">
Force Delete
</x-filament::button>

<x-filament::button wire:click="restore" color="gray" class="w-28">
Restore
</x-filament::button>
@endif
</div>
</x-slot>
<x-slot name="headerEnd">
<div class="flex flex-col space-y-2 md:flex-row md:space-y-0 md:space-x-2">
<x-filament::button wire:click="edit" class="w-28">
Edit
</x-filament::button>

@if(!$this->getIsSoftDeleted())
<x-filament::button wire:click="delete" color="danger" class="w-28">
Delete
</x-filament::button>
@endif

@if($this->getIsSoftDeleted())
<x-filament::button wire:click="forceDelete" color="danger" class="w-28">
Force Delete
</x-filament::button>

<x-filament::button wire:click="restore" color="gray" class="w-28">
Restore
</x-filament::button>
@endif
</div>
</x-slot>
When I click on one of the buttons, nothing happens but from what I've read online, this syntax should be correct?
6 Replies
ChesterS
ChesterS2y ago
Ngl, this is the 1st time I've seen this. Can you please share a link of where you saw this? Can you change one of the actions and add dd('something') to check if the actions are actually triggered? eg
public function delete(): void
{
dd("Deleting something");
Actions\DeleteAction::make();
}
public function delete(): void
{
dd("Deleting something");
Actions\DeleteAction::make();
}
Also, can I as why you're using actions if you want to create your own buttons? (especially since you're using filament buttons on your own template) Either way, your example will never work like this, AFAIK.
Damien
DamienOP2y ago
So the actions do trigger, you can see that in the image attached. As for the link, it was a mixture of seeing how the actions worked in the getHeaderActions method and talking with GPT to see if what I wanted to do was actually possible. I (probably wrongly) assumed that I would be able to pass the actions methods to by buttons to use. The reason for my own buttons is so the UI is consistent. I will grab an image.
No description
Damien
DamienOP2y ago
I have 2 widgets, and I want to be able to click buttons within the widget vs having some header actions for the view and some on the widget.
No description
Damien
DamienOP2y ago
Although, if it will never work, I better get back to the drawing board completely. Would you happen to know a better way of achieving what I am attempting to?
awcodes
awcodes2y ago
Try this:
<?php

namespace App\Filament\Resources\ContactResource\Widgets;

use Filament\Actions;
use Filament\Widgets\Widget;
use Illuminate\Database\Eloquent\Model;

class ContactOverview extends Widget
{
protected static string $view = 'filament.resources.contact-resource.widgets.contact-overview';

public ?Model $record = null;

public function getIsSoftDeleted(): bool
{
return $this->record['deleted_at'] !== null;
}

public function editAction(): void
{
Actions\EditAction::make('edit');
}

public function deleteAction(): void
{
Actions\DeleteAction::make('delete');
}

public function forceDeleteAction(): void
{
Actions\ForceDeleteAction::make('forceDelete');
}

public function restoreAction(): void
{
Actions\RestoreAction::make('restore');
}
}
<?php

namespace App\Filament\Resources\ContactResource\Widgets;

use Filament\Actions;
use Filament\Widgets\Widget;
use Illuminate\Database\Eloquent\Model;

class ContactOverview extends Widget
{
protected static string $view = 'filament.resources.contact-resource.widgets.contact-overview';

public ?Model $record = null;

public function getIsSoftDeleted(): bool
{
return $this->record['deleted_at'] !== null;
}

public function editAction(): void
{
Actions\EditAction::make('edit');
}

public function deleteAction(): void
{
Actions\DeleteAction::make('delete');
}

public function forceDeleteAction(): void
{
Actions\ForceDeleteAction::make('forceDelete');
}

public function restoreAction(): void
{
Actions\RestoreAction::make('restore');
}
}
<x-slot name="headerEnd">
<div class="flex flex-col space-y-2 md:flex-row md:space-y-0 md:space-x-2">
{{ $this->editAction }}

@if(!$this->getIsSoftDeleted())
{{ $this->deleteAction }}
@endif

@if($this->getIsSoftDeleted())
{{ $this->forceDeleteAction }}

{{ $this->restoreAction }}
@endif
</div>
</x-slot>
<x-slot name="headerEnd">
<div class="flex flex-col space-y-2 md:flex-row md:space-y-0 md:space-x-2">
{{ $this->editAction }}

@if(!$this->getIsSoftDeleted())
{{ $this->deleteAction }}
@endif

@if($this->getIsSoftDeleted())
{{ $this->forceDeleteAction }}

{{ $this->restoreAction }}
@endif
</div>
</x-slot>
you will probably need to pass the record into the widget and into each action though. I don't think the widget has default access to any records. so, i think the real issue here is that you are trying to use prebuilt actions that depend on a model / record. if you have a record you should be able to pass it to the action manually.
Action::make()->record($record)
Action::make()->record($record)
otherwise you would need to create custom actions instead of using the pre-built ones.
Damien
DamienOP2y ago
This is all really helpful, thank you. I do have access of the record within a widget as I access some of the other properties. Unless that is not what you mean.

Did you find this page helpful?