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
18.98k stars 2.93k forks source link

[object Object] display on simple repeater #8874

Closed valpuia closed 11 months ago

valpuia commented 1 year ago

Package

filament/filament

Package Version

3.0.67

Laravel Version

10.26.2

Livewire Version

3.0.5

PHP Version

8.2

Problem description

While using below code, it shows [object Object] in input field when creating

Repeater::make('invitations')
    ->simple(
        TextInput::make('email')
            ->email()
            ->required(),
    )

Screenshot from 2023-10-03 16-54-56

Try to fix here https://github.com/filamentphp/filament/pull/8845 but cannot figure out the problem

Expected behavior

Empty input field

Steps to reproduce

Clone, install Go to User, create new user and check Invitations repeater

Reproduction repository

https://github.com/valpuia/simple-repeater

Relevant log output

No response

valpuia commented 1 year ago

@valpuia if the result in the database that you are looking for is an array of emails you can simply change the TexInput name to 'invitations.email':

Yes this does the trick, thanks for head ups

ilpav12 commented 1 year ago

@valpuia if the result in the database that you are looking for is an array of emails you can simply change the TexInput name to 'invitations.email':

Yes this does the trick, thanks for head ups

Perfect! Please close the issue as completed.

valpuia commented 1 year ago

No it's not completed, unless the docs teach us like yours then we still want to see the empty input when declaring like docs

ilpav12 commented 1 year ago

You are correct that was not the right answer because it is empty on edit. It looks like that the is a difference between the value of the first TextInput and the others added manually:

"invitations" => array:2 [
    "cc35096d-4cfc-4207-bbc5-05b70db95fee" => array:1 [
      "email" => array:1 [
        "email" => null
      ]
    ]
    "e44bad27-018c-4ef2-af1e-2edd2947687b" => array:1 [
      "email" => null
    ]
  ]

This is why on the first he input shows '[object Object]'.

ilpav12 commented 1 year ago

This difference is generate by the Repeater class on lines 101 and 105:

foreach ($state ?? [] as $itemData) {
    $items[(string) Str::uuid()] = $simpleField ?
        [$simpleField->getName() => $itemData] :
        $itemData;
}

The same loop is present betwen lines 543 and 548. This generates the extra level that results in '[object Object]'. When inside the loop I simply put $items[(string) Str::uuid()] = $itemData; it works correctly. @zepfietje please let me know in what cases that code is necessary so I can make a PR.

valpuia commented 1 year ago

because it is empty on edit.

If you don't have any data then always empty on edit (this is normal for simple and main repeater)

When inside the loop I simply put $items[(string) Str::uuid()] = $itemData; it works correctly.

This one create problem in edit (if you have data)

Check this commit https://github.com/filamentphp/filament/pull/8845/commits/6258e82b97eda8e5f4a9e12f0948651bb4383a91, I revert back because of the above problem

jdion84 commented 1 year ago

i can confirm this is caused by defaultItems

when setting defaultItems(0), the new values do not show up as [object Object]

to fix this, i modified both occurences of this in the Repeater class:

            foreach ($state ?? [] as $itemData) {
                $items[(string) Str::uuid()] = $simpleField ?
                    [$simpleField->getName() => $itemData] :
                    $itemData;
            }

with this:

            foreach ($state ?? [] as $itemData) {
                $items[(string) Str::uuid()] = $itemData;
            }

however i am unsure if this will break something else, as i havent done any extensive testing on this yet

@danharrin do you think making this simple fix will break something else?

ilpav12 commented 1 year ago

@jdion84 as previously stated by @valpuia, this change will show empty fields on edit

jdion84 commented 1 year ago

i think i found a temporary workaround

add this to your simple repeater:

->default([''])
tuyenhv007 commented 1 year ago

Do you have used translation in Model?

JUEChristopher commented 11 months ago

i think i found a temporary workaround

add this to your simple repeater:

->default([''])

Not when your field is required, because this default() allow the user to skip it and it go throught the validation like that ...

danharrin commented 11 months ago

Fixed by #10046.

bartlomiej-przymus commented 11 months ago

@danharrin Thank you for the fix. You beat me to it! And it looks like your fix is working well on my test repo.

While I was working on this component I have noticed that default() method on Repeater runs twice even though $this->defaultItems(1); is set to one. I have noticed following two lines after debugging stack trace log that seem to be responsible for this behaviour: https://github.com/filamentphp/filament/blob/5b3fc20c7cea7b00bf924dc9b2455c4fca71c30a/packages/forms/src/Components/Concerns/HasState.php#L232-L234

Even though this does not seem to affect current functionality I think it might be a typo. Could you enlighten me on this?

danharrin commented 11 months ago

Typo! Please submit a PR