#How to determine if a form has changes

19 messages · Page 1 of 1 (latest)

wise spade
#

This has been posted elsewhere, but the solution hasn't been quite clear or evident. Making a new post to continue the discussion we started in order to not hijack the original question, which was slightly different.

The isDirty() method, when applied to '$record' will always be false, as $record will be linked to the original model. When applied to an instance of a livewire component, it still seems to return false whether any field has changed or not.

What I am trying to do is this: within an action that is in a form in a resource, to have different behavior based on if there any fields that have been changed or not by the user. I was able to do this by comparing the state to the original data, but this seems a bit cumbersome and also requires formatting datetimes and boolean values, since they maybe represented slightly differently in the database versus the livewire component.

#

@wanton vessel thank you for helping with this. This is a new discussion so we can look at this more specifically based on our conversation. I created some sample code to show what I am trying to do:

return $form
            ->schema([
                Forms\Components\Section::make('someActionsHere')
                    ->schema([
                        Actions::make([
                            Actions\Action::make('doSomethingHere')
                                ->action(function ($record) {
                                    if ($record->isDirty()) { // this clearly won't work as it is referring to the original model
                                        // do something here
                                        Notification::make('changes')  // just an example
                                            ->title('You have unsaved changes.')
                                            ->send();
                                    } else {
                                        // do something else here
                                        Notification::make('noChanges') // just an example
                                            ->title('All changes have been saved.')
                                            ->send();
                                    }
                                })
                        ]),
                    ]),
...
#

@wanton vessel you also mentioned using the wire dirty method, but I am not sure where I would put this since I don't have a custom blade view or anything like that for this resource.

remote osprey
#

You can inject $livewire into the ->action(function($livewire)) callback and access it there.

wise spade
# remote osprey You can inject $livewire into the ->action(function($livewire)) callback and acc...

Thanks.

I had tried that before, and that's how I was comparing the $livewire data vs the $record data to see if there were any changes. This worked, but it just felt like I was doing too much to get it done.

I was hoping there was something like an 'isDirty()' or 'hasChanges()', but those don't seem available in this context:

public static function form(Form $form): Form
    {
        return $form
            ->schema([
                Forms\Components\Section::make('someActionsHere')
                    ->schema([
                        Actions::make([
                            Actions\Action::make('doSomethingHere')
                                ->action(function ($livewire) {
                                    if ($livewire->isDirty()) {  // Method 'isDirty' not found in \Livewire\Component
                                        // do something here
                                        Notification::make('changes')  // just an example
                                            ->title('You have unsaved changes.')
                                            ->send();
                                    } else {
                                        // do something else here
                                        Notification::make('noChanges') // just an example
                                            ->title('All changes have been saved.')
                                            ->send();
                                    }
                                })
                        ]),
                    ]),
...

How would I determine if the component has any changes in this case? Thanks in advance.

#

This is what I had before that was working, but just doesn't seem very good:

->action(function ($livewire, $record) {
    $original = collect($record->getAttributes());
    $original['created_at'] = Carbon::parse($original['created_at'])->format('Y-m-d H:i:s');
    $original['updated_at'] = Carbon::parse($original['updated_at'])->format('Y-m-d H:i:s');

    $current = collect($livewire->data);
    $current['created_at'] = Carbon::parse($current['created_at'])->format('Y-m-d H:i:s');
    $current['updated_at'] = Carbon::parse($current['updated_at'])->format('Y-m-d H:i:s');

    if ($original != $current) {  // strict comparison was not working either
        // do something here
    } else {
        // do something else here
    }
                                  })
wanton vessel
#

I can't actually see any way to check programatically if anything is different. I thought we had isDirty() on the form within the livewire component but we don't. I think we could only do a collection compare, but then we would need to assoc it to make sure custom virtual / dehydrated fields are ignored too.

wise spade
remote osprey
#

Livewire does track it but I think it might only be on the JS side and therefore not available php side. Looking at filament’s own unsaved changes alert it’s all JS side.

#

here's one option, in your EditRecord and CreateRecord page classes add:

public bool $isDirty = false;

public function updating() {
    $this->isDirty = true;
}

Then you should be able to check it in the action callback:

->action(function ($livewire) {
  dd($livewire->isDirty);
})
wise spade
#

Thanks @remote osprey This works perfectly! Thanks to you and @wanton vessel for helping with this.

wanton vessel
#

Great work @remote osprey I forgot all about the updating method.

remote osprey
#

It’s kind of a hack and there may be some caveats but glad it works for you.

wise spade
#

Definitely a great solution for what I need.

#

Thanks again!

remote osprey
#

Could throw it in a trait too, if you need it on more than one resource.

wise spade
#

Nice, I will likely need it in more than one resource.

remote osprey
#

Haven’t tested further, but just fyi, I think the reason $record->isDirty() is always false is because something, possibly filament, is setting the record property to Locked. Possibly something to do with partial hydration. It’s above my head at that point. 😂 😅

wise spade
#

lol. Then in that case it is way, way above my head. But, I was expecting initially that $record->isDirty() would work, but quickly found out otherwise. 😂