damalalima
damalalima

Reputation: 21

Build Filament Subform

I'm using Laravel 11, Livewire 3 and Filament 3 and I have a problem or question about practice of my case.

I have a model "meetings" for some events happening. In this model i have some simple attributes like "name", "datefrom", dateto".... But also i have some related models like "persons" with attributes like "type", "name", "note"...

Now I want to create a filament form for creation of a meeting. This should be in a wizard because i have a lot of data to fill. The meeting-base-attributes are not a problem. i did it with TextInputs, Selects... But the challange is handling the related tables.

In the named example of persons i want some Inputs for "name", "type" an "note" and a button "add person" to add it to a list. I cant use a MultiSelect because there are more than one attributes for the persons.

I tried to handle this with a filament custom field:

Grid::make(1)
   ->schema([                                           
      EventsPersonList::make('person_list')
         ->label(false)
         ->default([])
         ->live()
       ])

In that custom-field i simple use an x-for expression to draw a table with the data from "person_list".

In my creation-form is use some Inputs and a ActionButton to send the data to "person_list":

TextInput::make('meeting_name')
    ->live()
    ->required(),

Select::make('person_type')
    ->live(onBlur: true)
    ->options(persons_type::all()->pluck('name', 'id'))
    ->searchable(),

TextInput::make('person_name')
    ->live()
    ->required(),

Textarea::make('person_note')
    ->live()
    ->rows(3)

Actions::make([
    Action::make('add_person')
        ->action(function (Livewire $livewire) {
            $livewire->dispatch('addperson');
        })
]),

As you see, i triggered an livewire event for sending the filled data to the custom field. Here is my dispatched event:

#[On('addperson')]
public function AddPerson()
{
    $form = $this->form->getState();

    $person = [
        'person_type' => !empty($form['person_type']) ? $form['person_type'] : null,
        'person_name' => !empty($form['person_name']) ? $form['person_name'] : null,
        'person_note' => !empty($form['person_note']) ? $form['person_note'] : null,
    ];
    $person_list[] = $person;

    $formdata = [
        'person_list' => $person_list,
    ];

    $this->form->fill($formdata);
}

First, this works very well. I can add persons and the person data is correctly stored in $data['person_list'].

BUT

You see i have a TextInput meeting_name in my form which ist validated with "required". Everything works as long i have data in my meeting_name before adding a person. Because a click on the ActionButton triggers the form validation. So if meeting_name is empty and i first want to add a person, the person will not added after pressing because filament shows the validation error and prevents adding the person.

This makes my thinking if this practice is the best way to handle this. I searched a lot if there is a way to prevent the ActionButton from doing the validation, but i messed up. I also thought about sub-forms but i didn't but it complexes the communication between the two forms.

So what is the best practice to handle my needs? Is there a way to prevent the action button to trigger the validation of the whole wizard page? Or is it better to build some kind of nested forms? If yes, how to do this best?

I tried to use subforms but i messed up with the communication between the form and the subform. I also tried to search a way to prevent the ActionButton from doing the form validation. I expect that the validation only happens if i click on wizards next and not on in-form-actions.

Upvotes: 2

Views: 27

Answers (0)

Related Questions