filamentphp / filament

A collection of beautiful full-stack components for Laravel. The perfect starting point for your next app. Using Livewire, Alpine.js and Tailwind CSS.
https://filamentphp.com
MIT License
17.76k stars 2.78k forks source link

stale UI values after update #2797

Closed ainesophaur closed 2 years ago

ainesophaur commented 2 years ago

Package

filament/spatie-tags-plugin

Package Version

^2.13.4

Laravel Version

v9.17.0

Livewire Version

v2.10.5

PHP Version

PHP 8.1.4

Bug description

When updating a form and remaining on the page, the tags input field will either retain removed values or will remove newly added values from the UI itself. The database receives the correct values and refreshes to the page will show the correct values. Currently using spatie/laravel-tags 4.3.2

I have tried with saving the relationship manually, and that causes the db to lose the correct values after update() was called. Also tried a combination of including tags in my form fill or leaving it empty/null

Attached are two screen caps, one for removing a tag and one for adding tags

Removing tag with manual refresh after

tags_issue

Adding tag with manual refresh after

tags_add_issue

Steps to reproduce

use Filament\Forms\Components\SpatieTagsInput;

class EditDemoComponent extends Component implements Forms\Contracts\HasForms {

use Forms\Concerns\InteractsWithForms;

    public $tags;
    public ModelWithHasTags $modelWithHasTags;

    protected function getFormSchema(): array
    {
        return [
            SpatieTagsInput::make('tags')
                ->type('support'),
        ];
    }

    protected function getFormModel(): ModelWithHasTags
    {
        return $this->modelWithHasTags;
    }    

    public function submit()
    {
        $this->modelWithHasTags->update($this->form->getState());
    }
}

Relevant log output

No response

danharrin commented 2 years ago

Could you add the following and try again please, the rest looks correct:

public function mount(): void
{
    $this->form->fill();
}
ainesophaur commented 2 years ago

@danharrin adding the above mount function fixed the issue. Now I only see the call to livewire to set the option and then another call to fetch the available options.

I know the documentation mentions filament/tables use filament/forms in the background, but I dont see any specifics in the documentation about adding a mount function (unlike the documentation for filament/forms.) I was curious if I should be adding the above method to all of my tables or if its only something to do for this issue.

danharrin commented 2 years ago

Hmm, for tables this should be called for you, but for the forms you need to do this yourself. Are you referring to #2815 as well?

danharrin commented 2 years ago

The form docs should hopefully make it very clear that calling form->fill() is mandatory for every form to be configured properly.

ainesophaur commented 2 years ago

:( I apologize as I was thinking I was viewing #2815 (which I prematurely updated as the issue for #2815 so disregard my previous update)

I didn't include a mount in my sample code above, but the actual code from the screen cap does include a mount function to fill in the form

public function mount(): void
    {      
        $this->form->fill([
            'ticket_board_id' => $this->ticket->ticket_board_id,
            'ticket_status_id' => $this->ticket->ticket_status_id,
            'ticket_priority_id' => $this->ticket->ticket_priority_id,
            'ticket_assigned_to_id' => $this->ticket->assigned_to_id,
        ]);

    }

FWIW I tried to add tags to the mount with no difference.. I ultimately left it out of the mount since it gets loaded/saved by the relationship

...
'tags' => $this->ticket->tagsWithType('support')->pluck('name')->toArray(),
...
danharrin commented 2 years ago

It looks like there are styling issues too, do you have console errors?

ainesophaur commented 2 years ago

The styling comes from overrides we're doing in CSS to match the rest of the inputs on the site. No console errors reported.

The only way I've been able to get around the issue is with another call to $form->fill() after calling $model->refresh() but it causes a UI blip between newState -> oldState -> newState

for example, my form submit calls a function which then emits an event, listened to by the form component

$this->emit("ticket." . $this->ticket->hashed_id . ".details.updated");


public function handleTicketDetailsUpdated()
    {
        $this->ticket->refresh();
        $this->form->fill([
            'ticket_board_id' => $this->ticket->ticket_board_id,
            'ticket_status_id' => $this->ticket->ticket_status_id,
            'ticket_priority_id' => $this->ticket->ticket_priority_id,
            'ticket_assigned_to_id' => $this->ticket->assigned_to_id,
            'tags' => $this->ticket->tagsWithType('support')->pluck('name')->toArray(),
        ]);
    }

If it helps, I can create an actual sample project (minus styling changes etc) and provide you with a repo URL.

ainesophaur commented 2 years ago

Ive created a sample sail based project which replicates the issue.

https://github.com/ainesophaur/filament-tags-issue-2797

danharrin commented 2 years ago

Fixed by #2999. Stupid tiny bug ahah