prowler
prowler
FFilament
Created by prowler on 7/12/2024 in #❓┊help
Relation manager custom action + Spatie media library plugin
Hello everyone, i have a relation manager which has a custom action in its $table -
Action::make('bom')
->model(Bom::class)
->label('Import Bom')
->form(Bom::getForm())
->action(function ($record, array $data): void {
Bom::updateOrCreate([
'assembly_id' => $record->id,
'bom_name' => $data['bom_name'],
'header_row_in_excel' => $data['header_row_in_excel'],
'last_row_in_excel' => $data['last_row_in_excel'],
]);
})
Action::make('bom')
->model(Bom::class)
->label('Import Bom')
->form(Bom::getForm())
->action(function ($record, array $data): void {
Bom::updateOrCreate([
'assembly_id' => $record->id,
'bom_name' => $data['bom_name'],
'header_row_in_excel' => $data['header_row_in_excel'],
'last_row_in_excel' => $data['last_row_in_excel'],
]);
})
Now, inside Bom::getForm() I have a media field using spatie's plugin which looks like this -
SpatieMediaLibraryFileUpload::make('bom_file')
->collection('bom_files')
SpatieMediaLibraryFileUpload::make('bom_file')
->collection('bom_files')
For some reason, when i upload a file, it is being attached to the parent model (Assembly) rather than to Bom, even though im explicitly using ->model() and the ->form() method is referencing to Bom's model as well.. So why is it happening?
2 replies
FFilament
Created by prowler on 7/5/2024 in #❓┊help
Is it possible to manage different resources (models) on each Step inside a Wizard?
All models have some basic relationships between them and the state should be maintained between the steps. I already figured out how to create a record after the first step using afterValidation(), but im struggling to pass the created model's id to the next step of the wizard in order to populate a Select component with a ->relationship(). Thanks in advace.
16 replies
FFilament
Created by prowler on 6/30/2024 in #❓┊help
Passing closure in viewData
In a Filament resource, I have some custom fields and right now im passing the record's data to the custom livewire view like this -
Forms\Components\View::make('engines')
->viewData([
'formValues' => [
'title' => $form->getRecord()?->title,
'subtitle' => $form->getRecord()?->subtitle,
'button_text' =>$form->getRecord()?->button_text,
'content' => $form->getRecord()?->content,
],

])->visible(fn(string $operation) => $operation === 'edit')
->columnSpanFull()
Forms\Components\View::make('engines')
->viewData([
'formValues' => [
'title' => $form->getRecord()?->title,
'subtitle' => $form->getRecord()?->subtitle,
'button_text' =>$form->getRecord()?->button_text,
'content' => $form->getRecord()?->content,
],

])->visible(fn(string $operation) => $operation === 'edit')
->columnSpanFull()
What i'd like to achieve is to make this component more granular so it will fit the create pages as well, which means that i need to pass the current data inside the form itself (from my experience - using Get $get), but the problem is that the viewData function is only receiving array and can't receive a Closure. How can i solve it? Thanks.
4 replies
FFilament
Created by prowler on 6/25/2024 in #❓┊help
Passing the record in the helperText method
is it possible to pass the $record in the helperText() function? tried doing it in the 'regular' way but it seems like $record is always null and im not sure why it behaves like this.
7 replies
FFilament
Created by prowler on 6/20/2024 in #❓┊help
Relocate Search Field in Table Builder
I'm interested in knowing if it's possible to move the search field integrated into the Table Builder to align it to the left instead of its current position on the right. Thank you for your assistance.
9 replies
FFilament
Created by prowler on 6/10/2024 in #❓┊help
is there a filament-ish intuitive way to listen to paste events on text fields?
i have some dynamic section which generates text fields on the fly.. is there a way i can attach an 'on paste' event to each of them to constantly check if a list of urls was pasted there, and if so - separate those with commas?
Forms\Components\Section::make('Fields')
->icon('heroicon-c-list-bullet')
->visible(function (callable $get) {
return (bool) $get('content_type_variation_id');
})
->schema(function (callable $get) {
$variationId = $get('content_type_variation_id');
if (! $variationId) {
return [];
}
$variation = ContentTypeVariation::with('fields')->find($variationId);
if (! $variation) {
return [];
}

return $variation->fields->map(function ($field) {
$fieldComponent = $field->type == '1'
? Forms\Components\TextInput::make("dynamic_fields.{$field->name}")->numeric()
: Forms\Components\TextInput::make("dynamic_fields.{$field->name}");
$fieldComponent->label($field->name);
$fieldComponent->default(fn ($get) => $get('dynamic_fields')[$field->name] ?? null);
if ($field->description) {
return Forms\Components\Section::make($field->name)
->description($field->description)
->schema([$fieldComponent]);
}

return $fieldComponent;
})->toArray();
}),
Forms\Components\Section::make('Fields')
->icon('heroicon-c-list-bullet')
->visible(function (callable $get) {
return (bool) $get('content_type_variation_id');
})
->schema(function (callable $get) {
$variationId = $get('content_type_variation_id');
if (! $variationId) {
return [];
}
$variation = ContentTypeVariation::with('fields')->find($variationId);
if (! $variation) {
return [];
}

return $variation->fields->map(function ($field) {
$fieldComponent = $field->type == '1'
? Forms\Components\TextInput::make("dynamic_fields.{$field->name}")->numeric()
: Forms\Components\TextInput::make("dynamic_fields.{$field->name}");
$fieldComponent->label($field->name);
$fieldComponent->default(fn ($get) => $get('dynamic_fields')[$field->name] ?? null);
if ($field->description) {
return Forms\Components\Section::make($field->name)
->description($field->description)
->schema([$fieldComponent]);
}

return $fieldComponent;
})->toArray();
}),
2 replies
FFilament
Created by prowler on 6/9/2024 in #❓┊help
Filament is saving relationship only on edit (update) pages but not on create.
Its the first time it happened to me and im not sure what im doing wrong. I have a BriefResource.php file which has 2 components which are relationships. one of them is a hasMany() relationship and the other one is many to many. I tried to copy and format the code here but it attached it as a paste file(?), never saw that in discord. Anyway, both of these fields are not saving on the create page but work just fine when i edit a brief and update it. What could be the reason? The is no special manipulation in CreateBrief.php whatsoever.
5 replies
FFilament
Created by prowler on 6/3/2024 in #❓┊help
Updating a text input after dispatching a job
Section::make('Originality Check')
->schema([
Forms\Components\TextInput::make('originality_check_result')
->label('Originality Check Result')
->live()
->disabled()
->default(fn ($record) => $record ? json_encode($record->originality_check_result) : null),
Forms\Components\Actions::make([
Action::make('checkOriginality')
->label('Check Originality')
->action(function ($livewire) {
$record = $livewire->form->getRecord();
self::dispatchOriginalityCheckJob($record);

}),
]),
])
Section::make('Originality Check')
->schema([
Forms\Components\TextInput::make('originality_check_result')
->label('Originality Check Result')
->live()
->disabled()
->default(fn ($record) => $record ? json_encode($record->originality_check_result) : null),
Forms\Components\Actions::make([
Action::make('checkOriginality')
->label('Check Originality')
->action(function ($livewire) {
$record = $livewire->form->getRecord();
self::dispatchOriginalityCheckJob($record);

}),
]),
])
The dispatchOriginalityCheckJob is updating the current article's originality_check_result field to the correct value, but it's not being reflected live on the form itself. Can I somehow force this 'refresh'?
11 replies
FFilament
Created by prowler on 6/2/2024 in #❓┊help
Dynamic languages using spatie's package
I am saving a list of languages per entry in my articles table, so for example, $article->languages can be ['es','de'] and sometimes it can be ['fr','nl'].. etc. Now, i worked with spatie/laravel-translatable in the past with no problem at all, when getTranslatableLocales() has a fixed set of languages, but when trying to populate the locale switcher dynamically by $article->languages - it fallbacks to the default config once language is changed. Here's how im trying to implement it at the moment on ArticleResource.php -
public static function getTranslatableLocales(): array
{
$recordId = request()->route('record');
$defaultLanguages = config('languages');
if ($recordId) {
$article = Article::find($recordId);
if ($article && !empty($article->languages)) {
return $article->languages;
}
}
return $defaultLanguages;
}
public static function getTranslatableLocales(): array
{
$recordId = request()->route('record');
$defaultLanguages = config('languages');
if ($recordId) {
$article = Article::find($recordId);
if ($article && !empty($article->languages)) {
return $article->languages;
}
}
return $defaultLanguages;
}
I noticed that once i change the language in the locale switcher (a simple Actions\LocaleSwitcher::make() on getHeaderActions()) - the $recordId is emptied, hence it retrieves the $defaultLnaguages instead. I guess there's a more way to access the current record instead of request()->route('record')
3 replies
FFilament
Created by prowler on 5/14/2024 in #❓┊help
Grouping by parent in a Select component
I have a 3 models - Brief, CustomOption and CustomOptionType. Each Brief belongs to many CustomOptionType with a pivot table -
public function customOptionTypes(): BelongsToMany
{
return $this->belongsToMany(CustomOptionType::class, 'brief_custom_option_types', 'brief_id', 'custom_option_type_id')
->withTimestamps();
}
public function customOptionTypes(): BelongsToMany
{
return $this->belongsToMany(CustomOptionType::class, 'brief_custom_option_types', 'brief_id', 'custom_option_type_id')
->withTimestamps();
}
And each CustomOptionType belongs to CustomOption -
public function customOption(): BelongsTo
{
return $this->belongsTo(CustomOption::class);
}
public function customOption(): BelongsTo
{
return $this->belongsTo(CustomOption::class);
}
Now, in BriefResource.php - I'd like to group this Select component by the 'parents' of the custom option types -
Select::make('Custom Options')
->label('Custom Options')
->preload()
->searchable()
->relationship('customOptionTypes', 'name')
->multiple(),
Select::make('Custom Options')
->label('Custom Options')
->preload()
->searchable()
->relationship('customOptionTypes', 'name')
->multiple(),
I know you can group them when explicitly using the ->options() function, but in this case im loading those directly via a relationship so im not sure how to achieve that. Thanks in advance.
6 replies
FFilament
Created by prowler on 4/17/2024 in #❓┊help
Dependant dropdowns don't load relationships on the Edit page.
Hello everyone. I have a resource called BriefResource and the model itself has a belongsTo() relationship to another model called ContentTypeVariation. The ContentTypeVariation has a belongsTo() relationship to ContentType model.
Now, on BriefResource.php i have this -
Forms\Components\Select::make('content_type_id')
->label('Content Type')
->options(ContentType::query()->pluck('name', 'id'))
->reactive()
->afterStateUpdated(fn (callable $set, $state) => $set('content_type_variation_id', null))
->default(function ($record) {
return $record ? optional($record->content_type_variation)->content_type_id : null;
}),

Forms\Components\Select::make('content_type_variation_id')
->relationship('content_type_variation', 'name')
->label('Content Type Variation')
->options(function (callable $get) {
$contentTypeId = $get('content_type_id');
return ContentTypeVariation::where('content_type_id', $contentTypeId)
->pluck('name', 'id');
})
->reactive()
->default(function ($record) {
return $record ? $record->content_type_variation_id : null;
})
Forms\Components\Select::make('content_type_id')
->label('Content Type')
->options(ContentType::query()->pluck('name', 'id'))
->reactive()
->afterStateUpdated(fn (callable $set, $state) => $set('content_type_variation_id', null))
->default(function ($record) {
return $record ? optional($record->content_type_variation)->content_type_id : null;
}),

Forms\Components\Select::make('content_type_variation_id')
->relationship('content_type_variation', 'name')
->label('Content Type Variation')
->options(function (callable $get) {
$contentTypeId = $get('content_type_id');
return ContentTypeVariation::where('content_type_id', $contentTypeId)
->pluck('name', 'id');
})
->reactive()
->default(function ($record) {
return $record ? $record->content_type_variation_id : null;
})
When im creating a new brief, i indeed get the correct content_type_variation_id in the DB.. but when im editing the entry, the dropdowns don't get populated at all.
6 replies
FFilament
Created by prowler on 4/15/2024 in #❓┊help
Is there a way to 'lock' an entry from being edited based on its current 'status' field?
Hello everyone. I know I can simply add a ->disabled on each field like this -
TextInput::make('title')
->disabled(fn (?Brief $record): bool => $record?->status === BriefStatusEnum::Processing->value)
TextInput::make('title')
->disabled(fn (?Brief $record): bool => $record?->status === BriefStatusEnum::Processing->value)
But, since the forms are big, i was wondering if there's a filament way to disable the whole form while the entry is held in certain status (Processing in this case..)? Thanks in advance.
5 replies
FFilament
Created by prowler on 4/14/2024 in #❓┊help
On ListResource.php - How to show only the resources which belong to the current user?
I am using filament's plugin for Spatie Laravel Permissions, and everything works just fine except this thing. I dont want to hide the whole resource from the navigation bar so viewAny() along with $post->user_id === auth()->user() won't fit here..
15 replies
FFilament
Created by prowler on 4/9/2024 in #❓┊help
Notifying the user after dispatching a background job once creating a new entry.
Right now im tackling it from the model's pov .. in Brief.php i have this part of code -
protected static function booted()
{
static::created(function ($brief) {
GenerateContentForBrief::dispatch($brief);
});
}
protected static function booted()
{
static::created(function ($brief) {
GenerateContentForBrief::dispatch($brief);
});
}
The job itself is doing bunch of things and eventually creates a new Article entry.. How can i notify the user in filament that their job is done? (Right now im using database driver for my jobs)
14 replies
FFilament
Created by prowler on 3/13/2024 in #❓┊help
Using Filament only as a "CRUD add-on" within a bigger app
I'm thinking of using Filament for its CSV import feature because I love the look and feel and Filament in general. Here's the plan: a user uploads a CSV, then the system prompts them to match columns using some dropdowns we set up in advance. After they confirm the import, they're directed to a new page showing a table (hopefully using Filament since it's already in my stack) filled with the processed CSV data. From there, they could, for example, click a 'get prices' button. The system would then take each row, consume some APIs, grab prices based on some logics, and update the table with those figures. My initial thought was using custom Livewire components along with Datatables so i'll be able to provide this "spreadsheet editing" vibe in real time.. but as there are other models which dont rely on CSV files neither on tables and i already have experience with Filament's panel builder (As a whole) - I thought about somehow mixing between both approaches.. I must admit i never used the forms/tables/infolists as separate components, but always was satisfied with the full admin panel that Filament provided .. Do you think Filament can help me shorten this flow somehow, or am I better off building something custom from scratch? Hope I was clear enough as english is not my mother tongue and sometimes it sounds crooked
8 replies
FFilament
Created by prowler on 2/6/2024 in #❓┊help
Repeater acts differently when used inside createOptionForm
Hello everyone, so here's the situation - I have a ComparisonTableResource which basically lets the user build comparison tables on the frontent and includes a list of Operators (a different model) and lets the user change their order in such way -
Repeater::make('operators')
->relationship('operators')
->schema([
Select::make('operator_id')
->label('Operator')
->options(\App\Models\Operator::all()->pluck('name', 'id')),
])
->reorderable()
->columnSpanFull(),
Repeater::make('operators')
->relationship('operators')
->schema([
Select::make('operator_id')
->label('Operator')
->options(\App\Models\Operator::all()->pluck('name', 'id')),
])
->reorderable()
->columnSpanFull(),
It works just fine and behaves as expected, including saving the correct order inside the pivot table between Operator and ComparisonTable (comparison_table_operator). Now, I have a different model and a resource called Lander in which the user can choose an existing comparison table or create a new one, like this (in LanderResource.php) -
Select::make('comparison_tables_id')
->relationship('comparison_table', 'title')
->createOptionForm([

Repeater::make('operators')
->relationship('operators')
->schema([
Select::make('operator_id')
->label('Operator')
->options(\App\Models\Operator::all()->pluck('name', 'id')),
])
->reorderable()
->columnSpanFull(),
]),
...
Select::make('comparison_tables_id')
->relationship('comparison_table', 'title')
->createOptionForm([

Repeater::make('operators')
->relationship('operators')
->schema([
Select::make('operator_id')
->label('Operator')
->options(\App\Models\Operator::all()->pluck('name', 'id')),
])
->reorderable()
->columnSpanFull(),
]),
...
Now, when simply selecting an existing comparison table - it works just fine, but when creating a new one and selecting the operators in the modal form, i get an error. saying SQLSTATE[HY000]: General error: 1364 Field 'name' doesn't have a default value.
16 replies
FFilament
Created by prowler on 10/9/2023 in #❓┊help
Adding a 'table' button on the RichEditor toolbar
Hello, is there an option to add a 'table' button on the trix editor which comens bundled with Filament? Most of the modern wysiwyg editors support this option of adding an html table into the wysiwyg.
5 replies
FFilament
Created by prowler on 10/4/2023 in #❓┊help
Automatically uploading and replacing external image URLs from pasted content in Filament's RichEdit
To be honest, I already asked this in Filament's github with no answer and im not fully sure its totally filament-related question, but i'll give it a shot anyway. My content editor prefers using Microsoft Word or Google Docs. After drafting, they copy the content and paste it directly into the WYSIWYG editor within my app, which uses Filament's RichEditor. Everything works smoothly, except for the images. When using Google Docs, the images are (obviously) hosted on Google's servers, resulting in image URLs like "https://lh3.googleusercontent.com/WY9Uz4l9...". I'd prefer to avoid this. Ideally, every image that's detected should be uploaded as if it were added directly through the WYSIWYG editor. At the moment, I already mutate the data before saving by using DeepL to translate the content into multiple languages:
protected function mutateFormDataBeforeCreate(array $data): array
{
$translatableLocales = ['en', 'es', 'it','de','nl', 'ro'];
$ignoreFields = ['author_id', 'created_at', 'updated_at'];

foreach ($data as $field => $value) {
if (in_array($field, $ignoreFields)) {
continue;
}
$translations = [];
$translations['en'] = $value;
foreach ($translatableLocales as $locale) {
if ($locale === 'en') {
continue;
}
$translatedText = $this->deeplService->translateText($value, NULL, $locale);
$translations[$locale] = $translatedText;
}
$data[$field] = $translations;
}
return $data;
}
protected function mutateFormDataBeforeCreate(array $data): array
{
$translatableLocales = ['en', 'es', 'it','de','nl', 'ro'];
$ignoreFields = ['author_id', 'created_at', 'updated_at'];

foreach ($data as $field => $value) {
if (in_array($field, $ignoreFields)) {
continue;
}
$translations = [];
$translations['en'] = $value;
foreach ($translatableLocales as $locale) {
if ($locale === 'en') {
continue;
}
$translatedText = $this->deeplService->translateText($value, NULL, $locale);
$translations[$locale] = $translatedText;
}
$data[$field] = $translations;
}
return $data;
}
I'm considering adding another mutator or modifying the existing one. The plan is to employ PHP's DOMDocument to parse the content's HTML, extract images, re-upload them to my own server, and then replace the old 'src' attributes with the new ones. However, I'm wondering if this approach is too convoluted. Is there perhaps a built-in mechanism in Filament that I'm unaware of which could simplify this process? Thanks
8 replies
FFilament
Created by prowler on 9/8/2023 in #❓┊help
livewire/livewire.js not found (404) on production only
after deploying my filament installation to production - i receive this console error saying GET https://domain.net/livewire/livewire.js?id=51f84ddf net::ERR_ABORTED 404 (Not Found) . it happens on the /admin/login page and it doesn't let me to proceed. weird thing is the livewire/livewire.js file is accessible when i enter it directly into the browser .. what might be the problem?
3 replies
FFilament
Created by prowler on 9/5/2023 in #❓┊help
Adding title to a stats overview widget
Hello, i created some simple stats overview widget with the php artisan command. How can i add a title above it? Haven't found anything in the documentation about that. Thanks in advance.
10 replies