pxlrbt / filament-activity-log

Spatie activity log integration into Filament
MIT License
144 stars 25 forks source link

Typed property Filament\Forms\Components\Component::$container must not be accessed before initialization #21

Open rtolinggi opened 1 year ago

rtolinggi commented 1 year ago

I encountered the error "Typed property Filament\Forms\Components\Component::$container must not be accessed before initialization" while using Filament v3.0-stable and PHP 8.1.

pxlrbt commented 1 year ago

Sorry, it's impossible to debug this without any code. What's the form schema for this?

rtolinggi commented 1 year ago

image

rtolinggi commented 1 year ago
class User extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable, HasRoles, LogsActivity;

    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'name',
        'email',
        'password',
    ];

    /**
     * The attributes that should be hidden for serialization.
     *
     * @var array<int, string>
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];

    /**
     * The attributes that should be cast.
     *
     * @var array<string, string>
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
        'password' => 'hashed',
    ];

    public bool $logFillable = true;
    public function getActivitylogOptions(): LogOptions
    {
        return LogOptions::defaults();
    }
}

in file UserResource\Pages

<?php

namespace App\Filament\Resources\UserResource\Pages;

use App\Filament\Resources\UserResource;
use pxlrbt\FilamentActivityLog\Pages\ListActivities;

class ListUserActivites extends ListActivities
{
    protected static string $resource = UserResource::class;
}
pxlrbt commented 1 year ago

That's the User model. Can you please share the form of your UserResource?

rtolinggi commented 1 year ago

class UserResource extends Resource { protected static ?string $model = User::class;

protected static ?string $navigationIcon = 'heroicon-m-users';

protected static ?string $navigationGroup = 'Pengaturan Pengguna';

protected static ?string $pluralLabel = 'Pengguna';

protected static ?string $label = 'Pengguna';

protected static ?string $modelLabel = 'Pengguna';

protected static ?string $recordTitleAttribute = 'email';

protected static ?int $navigationSort = 100;

public static function form(Form $form): Form
{
    $select = null;
    $roles = auth()->user()->getRoleNames();
    $exclude = ['super_admin', 'Admin Relawan'];
    if ($roles[0] === 'super_admin') {
        $select = Select::make('roles')
            ->label('Peran')
            ->required()
            ->native(false)
            ->preload()
            ->relationship('roles', 'name');
    } else {
        $select = Select::make('roles')
            ->label('Peran')
            ->required()
            ->native(false)
            ->preload()
            ->relationship('roles', 'name', modifyQueryUsing: fn (Builder $query) => $query->whereNotIn('name', $exclude));
    }

    return $form
        ->schema([
            Section::make('Pengguna')
                ->collapsible()
                ->schema([
                    TextInput::make('name')
                        ->label('Nama')
                        ->required(),
                    TextInput::make('email')
                        ->label('Email')
                        ->unique(ignoreRecord: true)
                        ->email()
                        ->required(),
                    TextInput::make('password')
                        ->label(static fn (Page $livewire): string => ($livewire instanceof EditUser) ? 'Kata Sandi Baru' : 'Kata Sandi')
                        ->password()
                        ->minLength(8)
                        ->dehydrateStateUsing(static fn (null|string $state): null|string => filled($state) ? Hash::make($state) : null)
                        ->required(static fn (Page $livewire): string => $livewire instanceof CreateUser)
                        ->maxLength(255)
                        ->dehydrated(static fn (null|string $state): bool => filled($state)),
                    $select,
                ])->columns(2)
        ]);
}

public static function table(Table $table): Table
{
    return $table
        ->columns([
            TextColumn::make('No')->rowIndex()->searchable(isGlobal: false),
            TextColumn::make('name')
                ->label('Nama'),
            TextColumn::make('email')
                ->badge()
                ->color('primary')
                ->label('Email'),
            TextColumn::make('roles.name')
                ->badge()
                ->color('success')
                ->label('Peran')
        ])
        ->filters([
            //
        ])
        ->actions([
            Action::make('activities')->url(fn ($record) => UserResource::getUrl('activities', ['record' => $record])),
            ActionGroup::make([
                ViewAction::make(),
                EditAction::make(),
                DeleteAction::make(),
            ]),
        ])
        ->bulkActions([
            Tables\Actions\BulkActionGroup::make([
                Tables\Actions\DeleteBulkAction::make(),
            ]),
        ])
        ->emptyStateActions([
            Tables\Actions\CreateAction::make(),
        ])
        ->headerActions([
            CreateAction::make()
                ->label('Tambah')
                ->icon('heroicon-m-plus-circle'),
        ]);
}

public static function getRelations(): array
{
    return [
        //
    ];
}

public static function getPages(): array
{
    return [
        'index' => Pages\ListUsers::route('/'),
        'create' => Pages\CreateUser::route('/create'),
        'activities' => Pages\ListUserActivites::route('/{record}/activities'),
        'edit' => Pages\EditUser::route('/{record}/edit'),
    ];
}

// public static function getEloquentQuery(): Builder
// {
//     return parent::getEloquentQuery();
// }

}

xiaoCreagia commented 1 year ago

same here, using filament v2

zach2825 commented 1 year ago

I'm getting that same error; it only happens when the data on the change is an object. If it's an empty array, the page loads.

The top one fails, and the page loads with the bottom one image

pxlrbt commented 1 year ago

It's not related to the data but to the form structure. It tries to get the name from the components and fails while accessing one of them. I guess it's a Section or Repeater or similar

fcno commented 9 months ago

Hey @pxlrbt .

I also have the same problem and I can share a very minimalist sequence of steps to reproduce the problem.

Let's assume a UserResource with at least 2 textinput ( 'email' and 'name') and ListUserActivities are in place.

  1. The form that works.
return $form
    ->schema([
        Forms\Components\TextInput::make('email')
            ->live(),

        Forms\Components\Group::make()
            ->schema(function (Forms\Get $get): array {
                return $get('email')
                ? [
                    Forms\Components\TextInput::make('name'),
                ]
                : [];
            }),
    ]);
  1. The form that DONT works. Just surround the form in a Section and $get('email'), will throw the error.
return $form
    ->schema([
    Forms\Components\Section::make(__('User'))
                    ->schema([

            Forms\Components\TextInput::make('email')
                ->live(),

            Forms\Components\Group::make()
                ->schema(function (Forms\Get $get): array {  // throw error
                    return $get('email')
                    ? [
                        Forms\Components\TextInput::make('name'),
                    ]
                    : [];
                }),
          ]),
    ]);
  1. Access the user activities page and you will see the error below caused by $get~
Typed property Filament\Forms\Components\Component::$container must not be accessed before initialization

I hope this helps in resolving the issue, or at least pointing out steps for accurately reproducing the error.

edeoliv commented 8 months ago

I have the same error in v3

cryptodev4 commented 8 months ago

Hi, I was checking the @fcno theory, then I made a test, I'm using the plugin https://filamentphp.com/plugins/bezhansalleh-shield for roles, so I've changed CheckboxList component to Select component, then it works.

So maybe the problem is in the Form components configuration or construction.

Ray-vV commented 8 months ago

Same problem here, I've got a Section in my form and some dependent fields. Doesn't work at all.

fcno commented 8 months ago

@pxlrbt It seems that this problem has gone away. I think that some update to the filament core ended up reflexively correcting the problem here.

I'm currently using version 3.2.17 of filament.

As this part of my code was commented out for a long time, I can't say which version of the filament ended up correcting the problem.

@Ray-vV Can u share your code and the filament version? try to use the latest version to see if the problem is gone.

pxlrbt commented 8 months ago

@pxlrbt It seems that this problem has gone away. I think that some update to the filament core ended up reflexively correcting the problem here.

Hm, interesting. I think there might still be issues with Sections or other Layout fields 🤔

Ray-vV commented 8 months ago

@pxlrbt It seems that this problem has gone away. I think that some update to the filament core ended up reflexively correcting the problem here.

I'm currently using version 3.2.17 of filament.

As this part of my code was commented out for a long time, I can't say which version of the filament ended up correcting the problem.

@Ray-vV Can u share your code and the filament version? try to use the latest version to see if the problem is gone.

Thanks for the suggestion, I decided to switch to the z3d0x/filament-logger for now. Not necesarrily due to this error however. But it turned out the z3d0x package was already more in the direction of what I wanted to implement into my project. I could do some testing on a seperate branch with this package if that aids you guys in any way.

nikosid commented 8 months ago

Unfortunately the problem is still here. And yes, changing CheckboxList to Select solves the problem.

AlexisSerneels commented 5 months ago

Same. Sorry.

GORGDEVELOPER commented 1 week ago

I had similar problem, so i fixed it by this code (I overwrite createFieldLabelMap method):

protected function createFieldLabelMap(): Collection
    {
        $form = static::getResource()::form(new Form($this));
        $record = $this->getRecord();

        $form->statePath('data');
        $form->fill($record->attributesToArray());
        $form->model($record);

        $components = collect($form->getComponents());
        $extracted = collect();

        while (($component = $components->shift()) !== null) {
            if ($component instanceof Field || $component instanceof MorphToSelect) {
                $extracted->push($component);

                continue;
            }

            $children = $component->getChildComponents();

            if (count($children) > 0) {
                $components = $components->merge($children);

                continue;
            }

            $extracted->push($component);
        }

        return $extracted
            ->filter(fn ($field) => $field instanceof Field)
            ->mapWithKeys(fn (Field $field) => [
                $field->getName() => $field->getLabel(),
            ]);
    }