Skip to main content
Tutorial Free

Filament: Add Form On Top Above The Table

December 02, 2023
3 min read

We recently received a question on our YouTube channel, so in this tutorial, we will answer it.

In this tutorial, we will see how we can add a form above a table list in a resource.

In this example, we have a Contact Laravel Model with a ContactResource Filament Resource with three required fields: first name, last name, and email.


Above the table, we can have widgets. Widgets are Livewire Component. Because of that, we can add the Filament Form to a Livewire Component. So first, let's create a widget and register it in the Resource.

php artisan make:filament-widget CreateContactWidget --resource=ContactResource

This command created a widget class app/Filament/Resources/ContactResource/Widgets/CreateContactWidget.php, and a view resources/views/filament/resources/contact-resource/widgets/create-contact-widget.blade.php.

app/Filament/Resources/ContactResource.php:

class ContactResource extends Resource
{
// ...
 
public static function getWidgets(): array
{
return [
ContactResource\Widgets\CreateContactWidget::class,
];
}
}

Next, we must add widget to a list page in the getHeaderWidgets method to show it above the table.

The getFooterWidgets method will show widget below the table.

app/Filament/Resources/ContactResource/ListContacts.php:

class ListContacts extends ListRecords
{
protected static string $resource = ContactResource::class;
 
protected function getHeaderActions(): array
{
return [
Actions\CreateAction::make(),
];
}
 
protected function getHeaderWidgets(): array
{
return [
ContactResource\Widgets\CreateContactWidget::class,
];
}
}

Now we can add a form to the CreateContactWidget widget.

app/Filament/Resources/ContactResource/Widgets/CreateContactWidget.php:

use Filament\Forms\Form;
use Filament\Widgets\Widget;
use Filament\Forms\Contracts\HasForms;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Concerns\InteractsWithForms;
 
class CreateContactWidget extends Widget implements HasForms
{
use InteractsWithForms;
 
protected static string $view = 'filament.resources.contact-resource.widgets.create-contact-widget';
 
protected int | string | array $columnSpan = 'full';
 
public ?array $data = [];
 
public function mount(): void
{
$this->form->fill();
}
 
public function form(Form $form): Form
{
return $form
->schema([
TextInput::make('first_name')
->required(),
TextInput::make('last_name')
->required(),
TextInput::make('email')
->email()
->required(),
])
->statePath('data');
}
}

To show the form in the view file, we must add the {{ $this->form }} inside the form.

resources/views/filament/resources/contact-resource/widgets/create-contact-widget.blade.php:

<x-filament-widgets::widget>
<x-filament::section>
<form wire:submit="create">
{{ $this->form }}
 
<x-filament::button type="submit" class="mt-3">
{{ __('filament-panels::resources/pages/create-record.form.actions.create.label') }}
</x-filament::button>
</form>
</x-filament::section>
</x-filament-widgets::widget>

We can see the form above the table.

Now, we can save the form and refresh the table to see new records without manually refreshing the page. In the forms wire:submit directive we provided, the create method will be called when clicking the create button.

app/Filament/Resources/ContactResource/Widgets/CreateContactWidget.php:

use App\Models\Contact;
 
class CreateContactWidget extends Widget implements HasForms
{
// ...
 
public function create(): void
{
Contact::create($this->form->getState());
$this->form->fill();
$this->dispatch('contact-created');
}
}

In the create method, we create a record, initialize a new form, and dispatch a Livewire event. Now, we must listen for this event on the list page and refresh the table.

app/Filament/Resources/ContactResource/ListContacts.php:

use Livewire\Attributes\On;
 
class ListContacts extends ListRecords
{
protected static string $resource = ContactResource::class;
 
#[On('contact-created')]
public function refresh() {}
 
// ...
}

And that's it. We have a form above the table in the filament resource.


The full source code is available in this GitHub repository.


If you want more Filament examples, you can find more real-life projects on our FilamentExamples.com.

Enjoyed This Tutorial?

Get access to all premium tutorials, video and text courses, and exclusive Laravel resources. Join our community of 10,000+ developers.

Recent Courses on Laravel Daily

Next.js Basics for Laravel Developers

11 lessons
58 min

Queues in Laravel 13

18 lessons
1 h 12 min read

How to Build Laravel 13 API From Scratch

30 lessons
1 h 23 min
aurawindsurfing avatar

cool!

TahinTech avatar

Thank you so much sir ..

Richard Thomas avatar

What a great tutorial, thank you!

Question for you... How would you handle the createOptionForm from a Select component?

I have it specified, yet when I click the + icon to bring up its own modal, nothing happens and there is nothing in the console that tells me anything useful.

Thanks!

Nerijus avatar

Hard to tell without debuging. Maybe there's a bug or maybe you are missing something.

Richard Thomas avatar

Definitely a strong possibility :)

I will continue to see if I can get this to work as everything else does.

I am not just not sure if the createOptionForm works with Formbuilder when the form is in a custom Livewire component. I'm not getting any console errors currently.

Zayed Hassan avatar

Just a quick tip. To show spinner inside the button after submiting the form, add form="create" to the button.

<x-filament::button type="submit" form="create" class="mt-3" wire:loading.attr="disabled"> {{ __('filament-panels::resources/pages/create-record.form.actions.create.label') }} </x-filament::button>

👍 2

We'd Love Your Feedback

Tell us what you like or what we can improve

Feel free to share anything you like or dislike about this page or the platform in general.