_andypeacock
_andypeacock
FFilament
Created by _andypeacock on 9/17/2024 in #❓┊help
A hint, not a question
Hi, just thought I'd share this hear as it took me a while to find the answer. If you need to populate a filament field from outside the alpine/livewire code (ie, in vanilla JS), do the following:
const targetField = document.getElementById('data.<field ID>');
targetField.value = event.data.html;
targetField.dispatchEvent(new Event('input'));
const targetField = document.getElementById('data.<field ID>');
targetField.value = event.data.html;
targetField.dispatchEvent(new Event('input'));
It's the event that's key, as that seems to update the actual alpine model, which then gets saved to the DB
4 replies
FFilament
Created by _andypeacock on 7/8/2024 in #❓┊help
Sort within group in table
Hi, I've got the following table:
public static function table(Table $table) : Table
{
return $table
->defaultGroup('project.name')
->columns([
Grid::make([
'lg' => 5,
])->schema([
TextColumn::make("created_at")->color('gray'),
TextColumn::make("name")
->extraAttributes([ 'class' => 'font-bold' ]),
TextColumn::make("description"),
TextColumn::make("activity.url")
->label("URL")
])
])
->actions([
Action::make('complete')
->hiddenLabel()
->icon('jam-circle')
->action(fn (Task $task) => $task->delete())
->visible(fn (Task $task) => ! $task->deleted_at)
,
Action::make('reopen')
->hiddenLabel()
->icon('jam-circle-f')
->action(fn (Task $task) => $task->restore())
->visible(fn (Task $task) => $task->deleted_at),
])
->modifyQueryUsing(fn (Builder $query) => $query->with('activity')->with('project')->withTrashed()->orderBy('deleted_at', 'asc'));
}
public static function table(Table $table) : Table
{
return $table
->defaultGroup('project.name')
->columns([
Grid::make([
'lg' => 5,
])->schema([
TextColumn::make("created_at")->color('gray'),
TextColumn::make("name")
->extraAttributes([ 'class' => 'font-bold' ]),
TextColumn::make("description"),
TextColumn::make("activity.url")
->label("URL")
])
])
->actions([
Action::make('complete')
->hiddenLabel()
->icon('jam-circle')
->action(fn (Task $task) => $task->delete())
->visible(fn (Task $task) => ! $task->deleted_at)
,
Action::make('reopen')
->hiddenLabel()
->icon('jam-circle-f')
->action(fn (Task $task) => $task->restore())
->visible(fn (Task $task) => $task->deleted_at),
])
->modifyQueryUsing(fn (Builder $query) => $query->with('activity')->with('project')->withTrashed()->orderBy('deleted_at', 'asc'));
}
That works well, but groups by project first, then by the task deleted status. So you get: Project A Undeleted Task A1 Undeleted Task A2 Project B Undeleted Task B1 Undeleted Task B2 Project A Deleted Task A3 Deleted Task A4 Project B Deleted Task B3 Deleted Task B4 What I'd like to get to is: Project A Undeleted Task A1 Undeleted Task A2 Deleted Task A3 Deleted Task A4 Project B Undeleted Task B1 Undeleted Task B2 Deleted Task B3 Deleted Task B4 Anyone know how to do this?
4 replies
FFilament
Created by _andypeacock on 7/8/2024 in #❓┊help
How to get table grid to align?
Hi, I've got the following code using the table grid, but the column tables don't line up. Any ideas on why? It's to do with the width of the actions, but I thought the grid was supposed to ensure everything aligned?
public static function table(Table $table) : Table
{
return $table
->recordUrl(null)
->defaultGroup('project.name')
->columns([
Grid::make([
'lg' => 5,
])->schema([
TextColumn::make("created_at")->color('gray'),
TextColumn::make("name")
->extraAttributes([ 'class' => 'font-bold' ]),
TextColumn::make("description"),
TextColumn::make("activity.url")
->label("URL")
->url(fn (Task $task) => $task->activity->url ?? null)
->openUrlInNewTab(true),

])
])
->actions([
Action::make('complete')
->label('Mark as Complete')
->icon('heroicon-s-check-circle')
->action(fn (Task $task) => $task->delete())
->visible(fn (Task $task) => ! $task->deleted_at)
,
Action::make('reopen')
->label('Re-Open')
->icon('heroicon-o-arrow-path')
->action(fn (Task $task) => $task->restore())
->visible(fn (Task $task) => $task->deleted_at),
])
->modifyQueryUsing(fn (Builder $query) => $query->with('activity')->with('project')->withTrashed()->orderBy('deleted_at', 'asc'));
}
public static function table(Table $table) : Table
{
return $table
->recordUrl(null)
->defaultGroup('project.name')
->columns([
Grid::make([
'lg' => 5,
])->schema([
TextColumn::make("created_at")->color('gray'),
TextColumn::make("name")
->extraAttributes([ 'class' => 'font-bold' ]),
TextColumn::make("description"),
TextColumn::make("activity.url")
->label("URL")
->url(fn (Task $task) => $task->activity->url ?? null)
->openUrlInNewTab(true),

])
])
->actions([
Action::make('complete')
->label('Mark as Complete')
->icon('heroicon-s-check-circle')
->action(fn (Task $task) => $task->delete())
->visible(fn (Task $task) => ! $task->deleted_at)
,
Action::make('reopen')
->label('Re-Open')
->icon('heroicon-o-arrow-path')
->action(fn (Task $task) => $task->restore())
->visible(fn (Task $task) => $task->deleted_at),
])
->modifyQueryUsing(fn (Builder $query) => $query->with('activity')->with('project')->withTrashed()->orderBy('deleted_at', 'asc'));
}
2 replies
FFilament
Created by _andypeacock on 5/27/2024 in #❓┊help
Update select with live API data
Hi all, I've got a select which has a suffixAction to reload options from an API:
Select::make('project_id')
->label('Project')
->options($this->projects)
->placeholder('Select a project')
->columnSpan(1)
->required()
->default('1207283586562118')
->suffixAction(
Action::make('refreshProjects')
->label('Refresh projects')
->icon('heroicon-o-arrow-path')
->action(function (Select $component) {
$this->updateProjects();
})

),
Select::make('project_id')
->label('Project')
->options($this->projects)
->placeholder('Select a project')
->columnSpan(1)
->required()
->default('1207283586562118')
->suffixAction(
Action::make('refreshProjects')
->label('Refresh projects')
->icon('heroicon-o-arrow-path')
->action(function (Select $component) {
$this->updateProjects();
})

),
But although updateProjects() does get the correct format data from API, I can't get it to re-load the select box from the new data. Any ideas how to do this? I've searched here, but nothing worked.
3 replies
FFilament
Created by _andypeacock on 5/17/2024 in #❓┊help
How to save morphToMany relationship during create?
Hi, I'm getting the error "Integrity constraint violation: 1048 Column 'categorizable_id' cannot be null" when laravel tries to run
insert into `categorizables` (`categorizable_id`, `categorizable_type`, `category_id`) values (?, App\Models\Content, 3)
insert into `categorizables` (`categorizable_id`, `categorizable_type`, `category_id`) values (?, App\Models\Content, 3)
The model has the following:
public function categories() : MorphToMany
{
return $this->morphToMany(Category::class, 'categorizable');
}
public function categories() : MorphToMany
{
return $this->morphToMany(Category::class, 'categorizable');
}
And the filament resource form has:
Select::make('categories')
->multiple()
->relationship(titleAttribute: 'name')
->createOptionForm([
TextInput::make('name')
->required(),
TextInput::make('description')
->required(),
Select::make('parent_id')
->options(
Category::get()
->pluck('name', 'id')
)
])
->preload()
->visible(function (Get $get) {
return $get('type') === 'post';
})
Select::make('categories')
->multiple()
->relationship(titleAttribute: 'name')
->createOptionForm([
TextInput::make('name')
->required(),
TextInput::make('description')
->required(),
Select::make('parent_id')
->options(
Category::get()
->pluck('name', 'id')
)
])
->preload()
->visible(function (Get $get) {
return $get('type') === 'post';
})
Obviously, the relationship can't be saved till after the parent Content model has been saved, but this seems be trying to do that in the reverse order. Any idea how to get round this? I can't believe I'm the first person to encounter this, so it feels like something I've set up wrong. Andy
9 replies
FFilament
Created by _andypeacock on 5/17/2024 in #❓┊help
Redirect unauthorised tenant user to their default tenant
The filament middleware IdentifyTenant::class returns a standard 404 if the user tries to access the subdomain of a tenant they are not allowed to access. Does anyone have a way to intercept/overwrite that, so I can redirect to a defined route?
2 replies
FFilament
Created by _andypeacock on 5/5/2024 in #❓┊help
Loading Indicators always spinning
No description
10 replies
FFilament
Created by _andypeacock on 1/5/2024 in #❓┊help
Plugin [awcodes/curator] is not registered for panel [admin]
Hi, After some issues with stancl/tenancy and fileupload (which I resolved by removing the stancl package), I've got file upload working, and decided to play with awcode's curator plugin. However, I'm getting the above error (which I don't think is a curator issue). I have two panels: control and admin. I'm trying to use the plugin only in the control one, which has config as follows:
$plugins = [
\BezhanSalleh\FilamentShield\FilamentShieldPlugin::make(),
\Awcodes\Curator\CuratorPlugin::make()
];

$panel
->id("control")
->path("/control")
->brandName("Control")
->login()
->emailVerification()
->passwordReset()
->colors($colors)
->discoverResources(in: app_path('Filament/Resources'), for: 'App\\Filament\\Resources')
->discoverPages(in: app_path('Filament/Pages/Mandatory'), for: 'App\\Filament\\Pages\\Mandatory')
->pages($pages)
->plugins($plugins)
->databaseNotifications()
->resources($resources)
->discoverWidgets(in: app_path('Filament/Widgets'), for: 'App\\Filament\\Widgets')
->widgets($widgets)
->middleware($middleware)
->authMiddleware($authMiddleware)
->navigationGroups([
'Content',
'Billing',
'Filament Shield',
]);
$plugins = [
\BezhanSalleh\FilamentShield\FilamentShieldPlugin::make(),
\Awcodes\Curator\CuratorPlugin::make()
];

$panel
->id("control")
->path("/control")
->brandName("Control")
->login()
->emailVerification()
->passwordReset()
->colors($colors)
->discoverResources(in: app_path('Filament/Resources'), for: 'App\\Filament\\Resources')
->discoverPages(in: app_path('Filament/Pages/Mandatory'), for: 'App\\Filament\\Pages\\Mandatory')
->pages($pages)
->plugins($plugins)
->databaseNotifications()
->resources($resources)
->discoverWidgets(in: app_path('Filament/Widgets'), for: 'App\\Filament\\Widgets')
->widgets($widgets)
->middleware($middleware)
->authMiddleware($authMiddleware)
->navigationGroups([
'Content',
'Billing',
'Filament Shield',
]);
I'm on the /control route, and the panel is displaying the brandname "control", and the plugin is listed if I do $panel->getPlugins() If I enable the plugin on the /admin panel, it then starts to work in /control, but I can't work out why filament is getting confused about the panel. I've search ControlPanelProvider.php and the Curator repo for "admin", and the word isn't used, so it's not like something is hard-coded... Any one seen this before?
16 replies
FFilament
Created by _andypeacock on 1/1/2024 in #❓┊help
Fileupload not saving to DB
Hi, I've got what I thought would be a simple fileupload component:
FileUpload::make('image')
->directory('blog-attachments')
->visibility('public')
->preserveFilenames()
->storeFileNamesIn('image')
->imageEditor()
->imageEditorAspectRatios([
null,
'16:9',
'4:3',
'1:1',
])
->moveFiles()
->columnSpan(2),
FileUpload::make('image')
->directory('blog-attachments')
->visibility('public')
->preserveFilenames()
->storeFileNamesIn('image')
->imageEditor()
->imageEditorAspectRatios([
null,
'16:9',
'4:3',
'1:1',
])
->moveFiles()
->columnSpan(2),
The DB column is called "image", it's a varchar(255). It's listed in the $fillable property of the model. The image file is uploaded to storage/app/livewire-tmp/ successfully. One point, it's saved in the format "4UwLQXBBr7UQzl9KU0PPfcFCPwM0AA-metaYXNhbmEtYm9hcmQucG5n-.png", rather then the original filenames, which I thought preserveFilenames() would prevent. The directory 'blog-attachments' is never created. Everything is good in the UI - no errors in the browser nor console. But when I save the resource, the image field in the DB is populated with "[]" If I change the component config to the bare minimum (FileUpload::make('image')), then the [] is replaced with a null. Any ideas?
50 replies
FFilament
Created by _andypeacock on 12/11/2023 in #❓┊help
How to reduce padding on table resource
No description
10 replies
FFilament
Created by _andypeacock on 10/9/2023 in #❓┊help
Change case of relationship name field in a select
Hi all, Looking for a bit of help on this one: I've got a Select field which works fine with a relationship:
Select::make('roles')
->label("Role")
->multiple(false)
->default('user')
->relationship('roles', 'name')
->required(),
Select::make('roles')
->label("Role")
->multiple(false)
->default('user')
->relationship('roles', 'name')
->required(),
However, the role names are slug format (super_user, account_admin) etc, and I'd like them to appear in the select as "Super User", "Account Admin", etc. I thought this would work:
->loadStateFromRelationshipsUsing(function (Select $component, $state) use ($highestLevel) {
$roles = Role::where('level', '<=', $highestLevel)
->orWhere('level', 1)
->orderBy('level')
->pluck('name', 'id')
->map(fn ($role) => ucwords(str_replace('_', ' ', $role)))
->toArray();
$component->state($roles);
})
->loadStateFromRelationshipsUsing(function (Select $component, $state) use ($highestLevel) {
$roles = Role::where('level', '<=', $highestLevel)
->orWhere('level', 1)
->orderBy('level')
->pluck('name', 'id')
->map(fn ($role) => ucwords(str_replace('_', ' ', $role)))
->toArray();
$component->state($roles);
})
But the if I add a logger() statement into the function, it's not even getting called. Any ideas how I can do this? Thanks in advance, Andy
7 replies
FFilament
Created by _andypeacock on 4/17/2023 in #❓┊help
Any way to get record in searchable()
Hi all, I'm trying to get the record in searchable() for a polymorphic relationship where the searchable model property varies according to the model. I can get this working to return the correct property value in the formatStateUsing(), but can't find a way to get the record in searchable() Any ideas? Regards, Andy
TextColumn::make('customer')
->sortable()
->formatStateUsing(function ($record) {
$class = $record->customer_type;
$identifier = config('billing.class_identifier')[$class];
return $record->customer->$identifier;
})
->searchable(query: function (Builder $query, string $search): Builder {
// Similar to the formatStateUsing() function above

// Get the record's class
// $class = $record->customer_type;

// Look up the classname in config() which returns the searchable field
// eg customer.email or team.name
// $identifier = config('billing.class_identifier')[$class];


// Use that field in the query.
// return $query
// query->where($identifier, 'like', "%{$search}%")

return $query;
})
TextColumn::make('customer')
->sortable()
->formatStateUsing(function ($record) {
$class = $record->customer_type;
$identifier = config('billing.class_identifier')[$class];
return $record->customer->$identifier;
})
->searchable(query: function (Builder $query, string $search): Builder {
// Similar to the formatStateUsing() function above

// Get the record's class
// $class = $record->customer_type;

// Look up the classname in config() which returns the searchable field
// eg customer.email or team.name
// $identifier = config('billing.class_identifier')[$class];


// Use that field in the query.
// return $query
// query->where($identifier, 'like', "%{$search}%")

return $query;
})
4 replies
FFilament
Created by _andypeacock on 4/5/2023 in #❓┊help
filter
Hi, Submitted a bug report for a KeyValue component missing the delete icon if there's only one row. I also found the offending line, but I'm not sure whether it's intentional? Happy to submit a PR if it's an accident. https://github.com/filamentphp/filament/issues/6132 Andy
3 replies
FFilament
Created by _andypeacock on 4/1/2023 in #❓┊help
Table Filter With All Entries From DB Column
8 replies