Nuekrato
Nuekrato
FFilament
Created by Nuekrato on 9/19/2024 in #❓┊help
Filament Panel assets not respecting X-Forwarded-Host Header
No description
4 replies
FFilament
Created by Nuekrato on 8/23/2024 in #❓┊help
FileUpload: How to handle file removal?
I need to show a checkbox if the upload contains executable files. This works for the initial file upload. But if the user removes files he already uploads (and removes the executables) the checkbox is still shown. I use the afterStateUpdate-method to hide/show the checkbox. But sadly afterStateUpdated is not called if a file is removed in the FileUpload-component. Is this a bug? Is there another method to achieve the desired behaviour?
1 replies
FFilament
Created by Nuekrato on 8/14/2024 in #❓┊help
How to use a custom policy for a custom resource page or disable authorization entirely?
Is it possible to use a custom policy for a custom resource page? Lets say I have a page to download files from an existing resource. I want to use a custom policy download for this resource. How can I manage access to the page? It seems like the model policies take precedence over the canAccess()-method of the page. So the "normal" model policies deny access to the custom resource download page, because I can't define the download policy for this resource page.
14 replies
FFilament
Created by Nuekrato on 8/13/2024 in #❓┊help
canAccess() is called on every page/resource AFTER logout resulting in an exception?
I use a default panel for Filament but I have problems on using the default logout - either frm the user dropdown in the top navigation bar or using the account widget logout button. After clicking logout Filament redirects and calls the /logout route using a POST request. During that I get an error 500 and the following exception (see logs attached). This is the method that produces the error from my FeatureSettingsPage:
public static function canAccess(): bool
{
return auth()->user()?->isAdmin();
}
public static function canAccess(): bool
{
return auth()->user()?->isAdmin();
}
So there is nothing special here. But the problem is very strange: Why should Filament call this method? After logging out I should be redirected to the login page and there is no need to call the canAccess() method on specific pages? I tried to return just true in the canAccess()-method but then Filament just calls the next canAccess-method from another page and so on. I removed the path for the panel provider because I want to host the default panel on the default path without any prefix: From my App\Providers\Filament\AppPanelProvider:
public function panel(Panel $panel): Panel
{
return $panel
->maxContentWidth(MaxWidth::Full)
->default()
->id('app')
->path('')
...
]);
}
}
public function panel(Panel $panel): Panel
{
return $panel
->maxContentWidth(MaxWidth::Full)
->default()
->id('app')
->path('')
...
]);
}
}
4 replies
FFilament
Created by Nuekrato on 8/8/2024 in #❓┊help
Table: How to position bulk action checkbox?
No description
4 replies
FFilament
Created by Nuekrato on 7/10/2024 in #❓┊help
Relation Manager: How to customize edit action?
Given the following example of a form in a relation manager:
public function form(Form $form): Form
{
return $form
->schema([
Checkbox::make('allowAllExtensions')
->label(__('templates.allow_all_extensions'))
->live()
->dehydrated(false)
->afterStateUpdated(function (Set $set) {
$set('allowed_file_extensions', ["*"]);
}),
Repeater::make('allowed_file_extensions')
->hidden(fn (Get $get) => $get('allowAllExtensions') === true)
->label(__('templates.allowed_file_extensions'))
->hint(__('templates.allowed_file_extensions_hint'))
->simple(
TextInput::make('extension')
->string()
->regex('/^([a-zA-Z0-9]+)$/u')
->required(),
),
]);
}
public function form(Form $form): Form
{
return $form
->schema([
Checkbox::make('allowAllExtensions')
->label(__('templates.allow_all_extensions'))
->live()
->dehydrated(false)
->afterStateUpdated(function (Set $set) {
$set('allowed_file_extensions', ["*"]);
}),
Repeater::make('allowed_file_extensions')
->hidden(fn (Get $get) => $get('allowAllExtensions') === true)
->label(__('templates.allowed_file_extensions'))
->hint(__('templates.allowed_file_extensions_hint'))
->simple(
TextInput::make('extension')
->string()
->regex('/^([a-zA-Z0-9]+)$/u')
->required(),
),
]);
}
How can I hook into the updating process of the edit action of the form? A lot of the docs only mention resource pages and not the relation manager itself. What I want to achieve: - Set the pivot model's attribute to ['*'] if the checkbox is selected. I tried it using afterStateUpdated but that doesn't work. I think I need to hook into the form's lifecycle but it seems like a Relation Manager does not have anything like https://filamentphp.com/docs/3.x/panels/resources/editing-records#customizing-data-before-saving nor https://filamentphp.com/docs/3.x/panels/resources/editing-records#customizing-the-saving-process. Also this https://filamentphp.com/docs/3.x/actions/prebuilt-actions/edit#customizing-the-saving-process doesn't work, because the EditAction is only indirectly used in the form method of the Relation Manager?
2 replies
FFilament
Created by Nuekrato on 5/28/2024 in #❓┊help
CheckboxList: modifyOptionsQueryUsing does not exist
The docs say there should be this method to modify the options but this method does not exist: https://filamentphp.com/docs/3.x/forms/fields/checkbox-list#customizing-the-relationship-query I currently need to accomplish exactly that: Set the relationship based on a different table than the options. Example code:
private function getPermissionsForm()
{
$checkboxLists = [];
foreach ($this->template->allowedTargets as $target) {
$checkboxLists[] = CheckboxList::make('templatePermissions')
->label($target->name)
->relationship(
name: 'templatePermissions',
titleAttribute: 'name',
modifyQueryUsing: fn (Builder $query) => $query->where('template_id', $this->template->id),
)
->options(function () use ($target) {
$permissions = [];
$templatePermissions = Permission::whereNull('model_id')->where('model_type', Project::class)
->where('destination_id', $target->id)->whereIn('name', ['download', 'upload'])->get();
foreach ($templatePermissions as $permission) {
$permissions[$permission->id] = $permission->name;
}
return $permissions;
})
->pivotData([
'template_id' => $this->template->id,
]);
}
return $checkboxLists;
}
private function getPermissionsForm()
{
$checkboxLists = [];
foreach ($this->template->allowedTargets as $target) {
$checkboxLists[] = CheckboxList::make('templatePermissions')
->label($target->name)
->relationship(
name: 'templatePermissions',
titleAttribute: 'name',
modifyQueryUsing: fn (Builder $query) => $query->where('template_id', $this->template->id),
)
->options(function () use ($target) {
$permissions = [];
$templatePermissions = Permission::whereNull('model_id')->where('model_type', Project::class)
->where('destination_id', $target->id)->whereIn('name', ['download', 'upload'])->get();
foreach ($templatePermissions as $permission) {
$permissions[$permission->id] = $permission->name;
}
return $permissions;
})
->pivotData([
'template_id' => $this->template->id,
]);
}
return $checkboxLists;
}
This code is inside a GroupRelationManager of a Template. A Group can belong to templatePermissions (which is the name of the relationship of the group) - but the options are coming from another table. Using the CheckboxList like this gives a wrong result. Also the modifyQueryUsing-method is not called as long as options is set. If I comment out ->options(...) the modifyQueryUsing is called.
5 replies
FFilament
Created by Nuekrato on 5/15/2024 in #❓┊help
Form: Adding user-defined pivot data to belongsToMany relationship
I have a form like this:
public static function form(Form $form): Form
{
return $form
->schema([
CheckboxList::make('allowedTargets')
->disabledOn('edit')
->relationship(name: 'allowedTargets', titleAttribute: 'name')
->pivotData([
TextInput::make('allowed_file_extensions')
->label('Allowed File Extensions')
->required(),
])
]);
}
public static function form(Form $form): Form
{
return $form
->schema([
CheckboxList::make('allowedTargets')
->disabledOn('edit')
->relationship(name: 'allowedTargets', titleAttribute: 'name')
->pivotData([
TextInput::make('allowed_file_extensions')
->label('Allowed File Extensions')
->required(),
])
]);
}
allowedTargets is a many-to-many-relationship of my Model. Each target has a pivot column allowed_file_extensions which accepts an array of file extensions as strings. Using a TextInput inside the pivotData()-method is not doing anything. But it is also not documented and was just an example what I already tried. I want the user be able to add allowed_file_extensions as pivot data on the create page of my Model. So he is able to create the parent model directly with the relationship and the specific pivot data. Is that possible? I also tried it using a RelationManager but it seems like RelationManagers don't show up on the resource create page.
5 replies
FFilament
Created by Nuekrato on 5/14/2024 in #❓┊help
Form: Nested JSON values are stored as string instead of integers
I have a form like:
public static function form(Form $form): Form
{
return $form
->schema([
TextInput::make('config.file_expire_days')
->integer()
->default(30)
->required(),
]);
}
public static function form(Form $form): Form
{
return $form
->schema([
TextInput::make('config.file_expire_days')
->integer()
->default(30)
->required(),
]);
}
And my model even casts the json values:
protected $casts = [
'config' => 'array',
'config->notify_project_expire_days' => 'array',
'config->project_expire_days' => 'integer',
'config->file_expire_days' => 'integer',
];
protected $casts = [
'config' => 'array',
'config->notify_project_expire_days' => 'array',
'config->project_expire_days' => 'integer',
'config->file_expire_days' => 'integer',
];
But if I save my form the model is created in the databse with string values in the JSON column (see the file_expire_days): {"base_path": "test", "file_expire_days": "15", "auto_delete_files": true, "project_expire_days": 30, "notify_project_expire_days": [14, "7", "1"]} If I leave the default value it is saved correctly as an integer. How can I tell filament that the values should be stored according to the model cast?
4 replies
FFilament
Created by Nuekrato on 5/8/2024 in #❓┊help
How to get $data from table form action?
I built a rather complex action in my table which looks like this:
->actions([
Action::make('permissions')
->form(function (User $record) {
$checkboxLists = [];
foreach ($this->project->targets as $target) {
$checkboxLists[] = CheckboxList::make('directPermissions')
->label($target->name)
->relationship(
titleAttribute: 'name'
)
->options(function () use ($target) {
$permissions = [];
foreach ($this->project->directPermissions()->where('destination_id', $target->id)->get() as $permission) {
$permissions[$permission->id] = $permission->name;
}
return $permissions;
});
}
return $checkboxLists;
})
->fillForm(function ($record) {
return $record->toArray();
})
->model(function ($record) {
return $record;
})
->action(function (array $data, $record, RelationManager $livewire) {
logger()->debug('Permissions data', $data);
})
])
->actions([
Action::make('permissions')
->form(function (User $record) {
$checkboxLists = [];
foreach ($this->project->targets as $target) {
$checkboxLists[] = CheckboxList::make('directPermissions')
->label($target->name)
->relationship(
titleAttribute: 'name'
)
->options(function () use ($target) {
$permissions = [];
foreach ($this->project->directPermissions()->where('destination_id', $target->id)->get() as $permission) {
$permissions[$permission->id] = $permission->name;
}
return $permissions;
});
}
return $checkboxLists;
})
->fillForm(function ($record) {
return $record->toArray();
})
->model(function ($record) {
return $record;
})
->action(function (array $data, $record, RelationManager $livewire) {
logger()->debug('Permissions data', $data);
})
])
This works perfectly fine and correctly sets the user's permissions in their project. The problem is that I am just not able to get the $data in the ->action -method. After submitting the form the $data seems to be empty: [2024-05-08 08:31:58] production.DEBUG: Permissions data So the ->action-method is triggered correctly but is not getting any data back from the form?
9 replies
FFilament
Created by Nuekrato on 5/7/2024 in #❓┊help
Custom field: bind array data
I created a custom field and this custom field renders mutliple Filament Checkboxes:
<x-dynamic-component :component="$getFieldWrapperView()" :field="$field">
<div x-data="{ state: $wire.$entangle('{{ $getStatePath() }}') }">
<!-- Interact with the `state` property in Alpine.js -->
<h1>Changing permissions for {{ $user()?->username}}</h1>
@foreach ($projectPermissions() as $permission)
<label>
<x-filament::input.checkbox x-model="state" />

<span>
{{ $permission->name }}
{{ $permission->destination->name }}
</span>
</label>
@endforeach
</div>

</x-dynamic-component>
<x-dynamic-component :component="$getFieldWrapperView()" :field="$field">
<div x-data="{ state: $wire.$entangle('{{ $getStatePath() }}') }">
<!-- Interact with the `state` property in Alpine.js -->
<h1>Changing permissions for {{ $user()?->username}}</h1>
@foreach ($projectPermissions() as $permission)
<label>
<x-filament::input.checkbox x-model="state" />

<span>
{{ $permission->name }}
{{ $permission->destination->name }}
</span>
</label>
@endforeach
</div>

</x-dynamic-component>
As you can see I bind the input to the state. The problem is that this binds every Checkbox to the state and this results in every checkbox using the same state (so only one true/false value for all checkboxes). How can I bind each checkbox to an array in the state?
55 replies