Create Widget with Form

Hello - is it possible to create a widget that generates a form? How would I do this?
25 Replies
Dan Harrin
Dan Harrin2y ago
using the form builder widgets are livewire components you can add forms to them with the form builder
bwurtz999
bwurtz999OP2y ago
Should the class extend Widget or extend Component? got it extends Widget implements Forms\Contracts\HasForms then use
protected function getFormSchema(): array
{
return [
Section::make('Title')
->schema([
TextInput::make('name'),
])
];
}
protected function getFormSchema(): array
{
return [
Section::make('Title')
->schema([
TextInput::make('name'),
])
];
}
and {{ $this->form }} in the view
Dan Harrin
Dan Harrin2y ago
dont forget $this->form->fill()
bwurtz999
bwurtz999OP2y ago
I want my form blank to start (expecting user input), but yes that's good to remember for autofilling with data. Thank you!
Dan Harrin
Dan Harrin2y ago
its mandatory in both cases, read the docs it initialises the form for use as well as filling it. if you dont use it, stuff like selects and file uploads wont work properly
bwurtz999
bwurtz999OP2y ago
Oh thank you I missed that @danharrin using $this->form->fill() throws an error, Method App\Filament\Widgets\TeamQuickAccess::form does not exist. But when I remove it everything works fine, including my form And when the user submits the form, the data is correct without using fill
Dan Harrin
Dan Harrin2y ago
please send the entire widget code
bwurtz999
bwurtz999OP2y ago
<?php

namespace App\Filament\Widgets;

use App\Models\Team;
use Filament\Widgets\Widget;
use Illuminate\Contracts\View\View;
use Filament\Forms;
use Filament\Forms\Components\Section;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Livewire\Component;

class TeamQuickAccess extends Widget implements Forms\Contracts\HasForms
{
use Forms\Concerns\InteractsWithForms;

protected static string $view = 'filament.widgets.team-quick-access';

protected int | string | array $columnSpan = 'full';

public $action = null;

public $teamId = null;

public function mount()
{
// $this->form()->fill();
}

protected function getFormSchema(): array
{
return [
Section::make('Quick Access')
->columns(2)
->schema([
Select::make('action')
->label('View')
->required()
->options([
'Flights' => 'Flights',
'Orders' => 'Orders',
]),
Select::make('teamId')
->required()
->label('Team')
->searchable()
->options(function() {
return Team::where('athletic', 1)->pluck('name', 'id')->toArray();
}),
])
];
}

public function submit()
{
dd($this);
}
}
<?php

namespace App\Filament\Widgets;

use App\Models\Team;
use Filament\Widgets\Widget;
use Illuminate\Contracts\View\View;
use Filament\Forms;
use Filament\Forms\Components\Section;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Livewire\Component;

class TeamQuickAccess extends Widget implements Forms\Contracts\HasForms
{
use Forms\Concerns\InteractsWithForms;

protected static string $view = 'filament.widgets.team-quick-access';

protected int | string | array $columnSpan = 'full';

public $action = null;

public $teamId = null;

public function mount()
{
// $this->form()->fill();
}

protected function getFormSchema(): array
{
return [
Section::make('Quick Access')
->columns(2)
->schema([
Select::make('action')
->label('View')
->required()
->options([
'Flights' => 'Flights',
'Orders' => 'Orders',
]),
Select::make('teamId')
->required()
->label('Team')
->searchable()
->options(function() {
return Team::where('athletic', 1)->pluck('name', 'id')->toArray();
}),
])
];
}

public function submit()
{
dd($this);
}
}
View:
<x-filament::widget>
<x-filament::card>

{{ $this->form }}

<x-filament::button wire:click="submit" id="cardButton" type="button" class="float-right">
{{ __('Submit') }}
</x-filament::button>

</x-filament::card>
</x-filament::widget>
<x-filament::widget>
<x-filament::card>

{{ $this->form }}

<x-filament::button wire:click="submit" id="cardButton" type="button" class="float-right">
{{ __('Submit') }}
</x-filament::button>

</x-filament::card>
</x-filament::widget>
Is there a way to add the submit button as a part of getFormSchema? It can be kind of a pain to get the styling/spacing right for the submit button when it's separate like that
Dan Harrin
Dan Harrin2y ago
$this->form->fill() not $this->form()->fill()
bwurtz999
bwurtz999OP2y ago
Ah thank you! Any idea on the submit button?
Dan Harrin
Dan Harrin2y ago
youre doing it right
bwurtz999
bwurtz999OP2y ago
Weird. It currently looks like this
bwurtz999
bwurtz999OP2y ago
Why does it show up outside of the card?
Dan Harrin
Dan Harrin2y ago
because its not in the form, but the card is actually i dont know why its not in the other card thats weird maybe wrap the button in a div?
bwurtz999
bwurtz999OP2y ago
<x-filament::widget>
<x-filament::card>

{{ $this->form }}

<div>
<x-filament::button wire:click="submit" id="cardButton" type="button" class="float-right">
{{ __('Submit') }}
</x-filament::button>
</div>

</x-filament::card>
</x-filament::widget>
<x-filament::widget>
<x-filament::card>

{{ $this->form }}

<div>
<x-filament::button wire:click="submit" id="cardButton" type="button" class="float-right">
{{ __('Submit') }}
</x-filament::button>
</div>

</x-filament::card>
</x-filament::widget>
Dan Harrin
Dan Harrin2y ago
i think its the float-right dont do that <div class="flex items-center justify-end">
bwurtz999
bwurtz999OP2y ago
Wow yup you were right Why does that mess it up?
Dan Harrin
Dan Harrin2y ago
because floats are bad lol
bwurtz999
bwurtz999OP2y ago
haha ok fair enough working perfectly now thank you!
Dan Harrin
Dan Harrin2y ago
you need a <form> element too
bwurtz999
bwurtz999OP2y ago
wrapping {{ $this->form }}?
Dan Harrin
Dan Harrin2y ago
<form wire:submit.prevent="submit"> <x-filament::button type="submit" NO WIRE CLICK> wrap the button and form, or just the card
bwurtz999
bwurtz999OP2y ago
oh ok. wire:click seemed to work why change it?
Dan Harrin
Dan Harrin2y ago
because this way has browser validation and also the ability to hit enter with any field and submit the form
bwurtz999
bwurtz999OP2y ago
Got it. Yes, both great features to make sure are included Thank you!
Want results from more Discord servers?
Add your server