Skip to content

fix: Child components receive null state when using array data with Infolist state()#41

Open
Luca-Lin wants to merge 1 commit into199ocero:3.xfrom
Luca-Lin:fix/array-state-handling
Open

fix: Child components receive null state when using array data with Infolist state()#41
Luca-Lin wants to merge 1 commit into199ocero:3.xfrom
Luca-Lin:fix/array-state-handling

Conversation

@Luca-Lin
Copy link

Problem

When using ActivitySection with array data passed via Infolist::state(), child components (ActivityTitle, ActivityDescription, ActivityDate, ActivityIcon) receive null from their $getState() method instead of the actual data.

Environment:

  • PHP 8.3
  • Filament 3.x (latest)
  • Laravel 10.x / 11.x

Example usage that fails:

public function activityInfolist(Infolist $infolist): Infolist
{
    return $infolist
        ->state([
            'activities' => [
                [
                    'title' => 'John Doe',
                    'description' => 'Created a new record',
                    'status' => 'create',
                    'created_at' => now(),
                ],
            ],
        ])
        ->schema([
            ActivitySection::make('activities')
                ->schema([
                    ActivityTitle::make('title'),
                    ActivityDescription::make('description'),
                    ActivityDate::make('created_at'),
                    ActivityIcon::make('status'),
                ]),
        ]);
}

Expected behavior: Child components display the data (title, description, etc.)
Actual behavior: Child components display placeholder text because $getState() returns null

Root Cause

In ActivitySection::getChildComponentContainers(), the method sets statePath($itemKey) for each child container, but when $itemData is an array (not a Model), the state data is not properly passed to child components:

foreach ($this->getState() ?? [] as $itemKey => $itemData) {
    $container = $this
        ->getChildComponentContainer()
        ->getClone()
        ->statePath($itemKey)
        ->inlineLabel(false);

    if ($itemData instanceof Model) {
        $container->record($itemData);  // Only Models get their data set
    }
    // Arrays are ignored - child components can't access the data!

    $containers[$itemKey] = $container;
}

Solution

Pass the array data to child containers using state() method when the data is not a Model:

foreach ($this->getState() ?? [] as $itemKey => $itemData) {
    $container = $this
        ->getChildComponentContainer()
        ->getClone()
        ->statePath($itemKey)
        ->inlineLabel(false);

    if ($itemData instanceof Model) {
        $container->record($itemData);
    } elseif (is_array($itemData)) {
        $container->state($itemData);
    }

    $containers[$itemKey] = $container;
}

Changes

  • Modified src/Components/ActivitySection.php to handle array data in getChildComponentContainers() method

@Luca-Lin
Copy link
Author

This is my first contribution to this project. If there are any issues with this fix, or if you have suggestions for a better approach, please let me know. I'm happy to make adjustments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant