Skip to content

Relationship still being saved even when ->dehydrated(false) #17778

@ralphjsmit

Description

@ralphjsmit

Package

filament/filament

Package Version

v4.0.12

Laravel Version

v12.28.1

Livewire Version

v3.6.4

PHP Version

8.3.25

Problem description

I am trying to convert some forms to use the new visibleJs()/hiddenJs() methods. One simple form example is a ToggleButtons field that selects an enum, and then a Select field that only is shown for one of the toggle button options.

Previously, I just used a ->live() and a ->visible(fn (Get $get) => $get('type') === ...) which worked fine, meaning that the second customer_id field would be dehydrated as null in the database. Even, in the situation that a user first selects a toggle button option that has the Select visible, the user selects a value from the Select and then the user changes the toggle button again so that the Select is hidden. In that case, even if the Select has a state selected, as it is not visible it was still dehydrated/saved as null.

Now, I converted this setup to a visibleJs(). This works ok, but I noticed that when the Select has a state and is then made hidden again, the value is still being dehydrated. That is then understandable, as the Filament backend has no way to know whether a field is hidden or visible in JS. To solve that then, I wanted to apply a ->dehydrated(fn () => false) closure, that would tell Filament to not dehydrate the field.

However, Filament still dehydrates the field. I suspect that is because of the ->relationship()-call. In my opinion, I think these relationships should respect the ->dehydrated() as well, because otherwise in the below example I do not see any way to convert this to the ->visibleJs() method.

ToggleButtons::make('type')
    ->options(DocumentType::class)
    ->inline()
    ->required(),
Select::make('customer_id')
    ->relationship('customer', 'name')
    ->searchable()
    ->preload()
    ->visibleJs(function () {
        $documentTypeCustomer = DocumentType::Customer;

        return <<<JS
            \$get('type') === '{$documentTypeCustomer->value}'
        JS;
    })
    ->dehydrated(function (Get $get) {
        $type = $get('type');

        ray($type);

        $documentTypeCustomer = DocumentType::Customer;

        $isDehydrated = $type === $documentTypeCustomer;

        ray('Dehydrated customer id: ' . $isDehydrated ? 'true' : 'false');

        return $isDehydrated;
    })
    ->requiredUnless('type', DocumentType::Customer->value),

There are two methods like ->saveRelationshipsWhenDisabled() and ->saveRelationshipsWhenHidden(). But I think I am of the opinion that a relationship should not be saved if the field is not dehydrated.

Expected behavior

See above.

Steps to reproduce

  1. Go to Documents > Create.
  2. Select the value "Customer-specific document"
  3. Select a customer
  4. Then switch back to type "Global document".
  5. Then save the document.

I expect the customer_id field to be null in the database.

Reproduction repository (issue will be closed if this is not valid)

https://github.com/ralphjsmit/demo/tree/rjs/bug-report-dehydrate

Relevant log output

Metadata

Metadata

Assignees

No one assigned

    Projects

    Status

    Todo

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions