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
getFooterWidgetsmethod 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.
                                                    
                                                    
                                                    
cool!
Thank you so much sir ..
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!
Hard to tell without debuging. Maybe there's a bug or maybe you are missing something.
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.
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>