Quadrubo / filament-model-settings

Model specific settings for your filament project.
MIT License
14 stars 1 forks source link

[Bug]: Repeater field crashes when trying to reorder items #9

Open PunchRockgroin opened 5 months ago

PunchRockgroin commented 5 months ago

What happened?

I have a nested array which is reorderable, with data set up on a model using the HasSettingsField trait on an existing model. Using the Repeater field, the defaultSettings load normally, and save correctly. However, when trying to reorder the Repeater entries, I get:

Filament\Forms\ComponentContainer::getRawState(): Return value must be of type Illuminate\Contracts\Support\Arrayable|array, int returned

How to reproduce the bug

Using the following default settings on the model:

    public $defaultSettings = [
        'pre_event_stages' => [
            [
                'name' => 'Created',
                'slug' => 'created',
                'stageVersionNumber' => '01',
                'legacyFolderName' => '1_Master',
                'custom_difficulty_options' => []
            ],
            [
                'name' => 'Design',
                'slug' => 'design',
                'stageVersionNumber' => '02',
                'legacyFolderName' => '2_Design',
                'custom_difficulty_options' => []
            ],
            [
                'name' => 'Copy',
                'slug' => 'copy',
                'stageVersionNumber' => '03',
                'legacyFolderName' => '3_Copy',
                'custom_difficulty_options' => []
            ],
            [
                'name' => 'QA',
                'slug' => 'qa',
                'stageVersionNumber' => '04',
                'legacyFolderName' => '4_QA',
                'custom_difficulty_options' => [
                    [
                        'value' => 0,
                        'name' => 'Review',
                        'description' => 'We have clicked through your presentation and have made no edits.'
                    ],
                    [
                        'value' => 1,
                        'name' => 'Minor',
                        'description' => 'We have made minor edits to your presentation to ensure brand compliance.'
                    ],
                    [
                        'value' => 2,
                        'name' => 'Update',
                        'description' => 'We made minor edits to HPE slides for brand compliance and added the survey slide.'
                    ],
                    [
                        'value' => 3,
                        'name' => 'Revised',
                        'description' => 'We have made edits to your presentation to ensure brand compliance. For slides that we created revised graphics, we have kept your original slide in the back-up slides at the end of the presentation.'
                    ],
                ]
            ],
            [
                'name' => 'Ready to Upload',
                'slug' => 'ready-to-upload',
                'stageVersionNumber' => '05',
                'legacyFolderName' => '5_Ready to Upload',
                'custom_difficulty_options' => []
            ]
        ],
        'encounter_difficulty_options' => [
            [
                'value' => 0,
                'name' => 'Review',
                'description' => 'We have clicked through your presentation and have made no edits.'
            ],
            [
                'value' => 1,
                'name' => 'Minor',
                'description' => 'We have made minor edits to your presentation to ensure brand compliance.'
            ],
            [
                'value' => 2,
                'name' => 'Update',
                'description' => 'We made minor edits to HPE slides for brand compliance and added the survey slide.'
            ],
            [
                'value' => 3,
                'name' => 'Revised',
                'description' => 'We have made edits to your presentation to ensure brand compliance. For slides that we created revised graphics, we have kept your original slide in the back-up slides at the end of the presentation.'
            ],
        ],
    ];

Then, set the following on the model itself:

                            Repeater::make('settings.pre_event_stages')
//                                ->collapsed()
                                ->itemLabel(fn ($state): ?string => $state['name'] ?? null)
                                ->columns(2)
                                ->schema([
                                    TextInput::make('name')->required(),
                                    TextInput::make('slug')->required(),
                                    TextInput::make('stageVersionNumber')->required(),
                                    TextInput::make('legacyFolderName')->required(),
                                    Repeater::make('custom_difficulty_options')
                                        ->itemLabel(fn (array $state): ?string => $state['name'] ?? null)
//                                        ->collapsed()
                                        ->schema([
                                            TextInput::make('name')->required(),
                                            TextInput::make('value')
                                                ->numeric()
                                                ->inputMode('decimal')
                                                ->step(0.1)
                                                ->required(),
                                            TextInput::make('description')->required(),
                                        ])
                                        ->columnSpanFull()
                                        ->isModelSetting()
                                ])
                                ->isModelSetting()
                            ,
                            Repeater::make('settings.encounter_difficulty_options')
                                ->itemLabel(fn (array $state): ?string => $state['name'] ?? null)
//                                ->collapsed()
                                ->schema([
                                    TextInput::make('name')->required(),
                                    TextInput::make('value')
                                        ->numeric()
                                        ->inputMode('decimal')
                                        ->step(0.1)
                                        ->required(),
                                    TextInput::make('description')->required(),
                                ])
                                ->columns(2)
                                ->isModelSetting()
                        ]),

Saving works fine, however, re-ordering will trigger Filament\Forms\ComponentContainer::getRawState(): Return value must be of type Illuminate\Contracts\Support\Arrayable|array, int returned

The Repeater field works and re-orders when you remove 'isModelSetting()' from each repeater and when used as a standalone repeater field in it's own JSON database column, though without the 'defaults' being populated.

Package Version

1.1.0

PHP Version

8.2.1

Laravel Version

10.42.0

Which operating systems does with happen with?

No response

Notes

No response

github-actions[bot] commented 4 months ago

This issue is stale because it has been open for 30 days with no activity.

Quadrubo commented 4 months ago

Hey, sorry I took so long. I managed to take a look at this but wasn't able to reproduce this behaviour. Could you provide a more minimal example that also doesn't work for you? It would be best if you'd provide some kind of reproduction repo I can setup to have a look at.

PunchRockgroin commented 3 months ago

No worries. I'm actually struggling to get it to work at all with a base Filament/Laravel 11 install. Not sure if this is a Laravel 11 issue, Herd or a SQLite issue, or if it's something else, but the $defaultSettings are not applying or being seen in Filament using the example color and can_add_students setup at https://github.com/Quadrubo/filament-model-settings?tab=readme-ov-file#settings-within-your-existing-resouce

I'll keep trying to get it to work and get back to you when I can.

PunchRockgroin commented 3 months ago

I've got it working, and an example repo is here: https://github.com/PunchRockgroin/Filament-Model-Settings-Reorder-Issue

I've added a sqlite database at database/database.sqlite that's ready to go, with logins of test@test.com and secret and content added already.

Steps to reproduce:

  1. Log in
  2. Go to Hopper Events in sidebar
  3. Edit one that is already there, or create a new Hopper Event then edit.
  4. Try to reorder one of the repeaters in the Encounter Difficulty Options field
  5. You will get the error.

https://github.com/Quadrubo/filament-model-settings/assets/1855836/225636d4-85ec-4e1c-b958-bb04291b1201

However, if you comment out isModelSetting() on the field and then change the cast to "array" as noted in https://filamentphp.com/docs/3.x/forms/fields/repeater#overview, and reorder, the error does not appear and the reorder can be saved.

I do note that https://github.com/glorand/laravel-model-settings/issues/92 says not to cast as array, and this https://github.com/filamentphp/filament/issues/8370 is the only other mention of the Filament\Forms\ComponentContainer::getRawState(): Return value must be of type Illuminate\Contracts\Support\Arrayable|array, int returned error message.

Let me know if you need any further information!

github-actions[bot] commented 2 months ago

This issue is stale because it has been open for 30 days with no activity.

zepfietje commented 2 months ago

Isn't this just a bug in Filament core? I'm running into the same thing.

Edit: my issue was caused by a custom addAction.

Quadrubo commented 2 months ago

Have tried debugging this a bit. When retrieving the raw state in the function getRawState(). The data_get function tries to destructure the Livewire object. In the livewire object, the options duplicated themselves with integer values which causes the return problem.

grafik

With a normal json repeater this doesn't happen.

grafik

I however have no idea what causes this.

github-actions[bot] commented 1 month ago

This issue is stale because it has been open for 30 days with no activity.