Blackpig
Blackpig
FFilament
Created by Blackpig on 8/30/2024 in #❓┊help
Dynamic placeholder content renders HTML as text string not mark-up
No description
4 replies
FFilament
Created by Blackpig on 7/15/2024 in #❓┊help
Disable entire form - throws error when checking $operation
I want to disable my edit form when certain criteria are met.
I don't want to do it on a field by field basis as this is a fairly large and complex form (also why I don't want a view). Snippet from my resource:
public static function form(Form $form): Form
{
return $form
->disabled(fn (?Quote $record, string $operation): bool => $operation == 'edit' && $record->status == 'final')
->schema([])
public static function form(Form $form): Form
{
return $form
->disabled(fn (?Quote $record, string $operation): bool => $operation == 'edit' && $record->status == 'final')
->schema([])
But this throws An attempt was made to evaluate a closure for [Filament\Forms\Form], but [$operation] was unresolvable. https://flareapp.io/share/17DXjr67 I thought the $operation helper was globally available Small caveat - I've rushed my dog to the vets 3 times in the last 7 days so I'm a bit emotionally frazzled - I'm sure the answer is blindingly obvious nbl
6 replies
FFilament
Created by Blackpig on 7/1/2024 in #❓┊help
Custom layout - setting data from $get throws fatal Typed property initialization error
Flare error is here https://flareapp.io/share/LPd8ElvP I am creating a quote worksheet with a Custom layout component:
<?php

namespace App\Forms\Components;

use Filament\Forms\Components\Component;

class QuoteSummary extends Component
{
protected string $view = 'forms.components.quote-summary';
public array $viewData = [];


public static function make(): static
{
return app(static::class);
}

public function viewData(array | \Closure $viewData): static
{
$this->viewData = $this->evaluate($viewData);
return $this;
}

public function getViewData(): array
{
return $this->viewData;
}
}
<?php

namespace App\Forms\Components;

use Filament\Forms\Components\Component;

class QuoteSummary extends Component
{
protected string $view = 'forms.components.quote-summary';
public array $viewData = [];


public static function make(): static
{
return app(static::class);
}

public function viewData(array | \Closure $viewData): static
{
$this->viewData = $this->evaluate($viewData);
return $this;
}

public function getViewData(): array
{
return $this->viewData;
}
}
and i'm trying to pass into the ->viewData method calculated values from other fields on the form
QuoteSummary::make()
->viewData(function (GET $get):array {
//return [];
$visits = $get('no_of_return_trips') * 2;
$distance_cost = $get('distance') * $visits * $get('distance_cost_per_km');
$driving_cost = $get('driving_time') / 60 * $get('driving_time_cost_per_hour');
$tolls = $get('tolls');
$parking = $get('parking_fees');
$van_hire = $get('requires_van_hire') ? $get('van_hire_charge') : 0;
$travel = $distance_cost + $driving_cost + $tolls + $parking + $van_hire;
$accommodation = $get('requires_accommodation') ? $get('accomm_no_of_staff') * $get('accomm_no_of_nights') * $get('accommodation_cost_per_person_per_night') : 0;

$return = [
'Travel' => '€' . number_format($travel, 2),
'Accommodation' => '€' . number_format($accommodation, 2),
'Catering' => '€0.00',
'Equipment' => '€0.00',
'Service Team' => '€0.00',
'Additional charges' => '€0.00',
];
return $return;
}),
QuoteSummary::make()
->viewData(function (GET $get):array {
//return [];
$visits = $get('no_of_return_trips') * 2;
$distance_cost = $get('distance') * $visits * $get('distance_cost_per_km');
$driving_cost = $get('driving_time') / 60 * $get('driving_time_cost_per_hour');
$tolls = $get('tolls');
$parking = $get('parking_fees');
$van_hire = $get('requires_van_hire') ? $get('van_hire_charge') : 0;
$travel = $distance_cost + $driving_cost + $tolls + $parking + $van_hire;
$accommodation = $get('requires_accommodation') ? $get('accomm_no_of_staff') * $get('accomm_no_of_nights') * $get('accommodation_cost_per_person_per_night') : 0;

$return = [
'Travel' => '€' . number_format($travel, 2),
'Accommodation' => '€' . number_format($accommodation, 2),
'Catering' => '€0.00',
'Equipment' => '€0.00',
'Service Team' => '€0.00',
'Additional charges' => '€0.00',
];
return $return;
}),
Thanks for any light that can shed on this
4 replies
FFilament
Created by Blackpig on 6/21/2024 in #❓┊help
Add an option to Checkboxlist via an Action
I'm trying to recreate similar behaviour to the ->createOptionForm() of the Form\Select component https://filamentphp.com/docs/3.x/forms/fields/select#creating-a-new-option-in-a-modal but on a CheckboxList. I was hoping I could utilise either the ->helpertext() or ->hint() methods and trigger an Action. It renders ok - but the Action doesn't trigger the modal/form - is this possible or do I need top change my approach?
CheckboxList::make('roles')
->helperText(function(): Action {
return Action::make('createRole')
->label('Add a new role')
->link()
->form([
TextInput::make('title')
->required(),
TextInput::make('hourly_rate')
->label('Hourly Rate')
->required()
->type('number')
->inputMode('decimal')
->default('25.00'),
])
->action(function (array $data): void {
$newRole = new StaffRole;
$newRole->title = $data['title'];
$newRole->hourly_rate = $data['hourly_rate'];
$newRole->save();
});
})
//->url(fn() => route('filament.admin.resources.staff-roles.create'))
->required()
->relationship(titleAttribute: 'title')
->columns(4)
]);
CheckboxList::make('roles')
->helperText(function(): Action {
return Action::make('createRole')
->label('Add a new role')
->link()
->form([
TextInput::make('title')
->required(),
TextInput::make('hourly_rate')
->label('Hourly Rate')
->required()
->type('number')
->inputMode('decimal')
->default('25.00'),
])
->action(function (array $data): void {
$newRole = new StaffRole;
$newRole->title = $data['title'];
$newRole->hourly_rate = $data['hourly_rate'];
$newRole->save();
});
})
//->url(fn() => route('filament.admin.resources.staff-roles.create'))
->required()
->relationship(titleAttribute: 'title')
->columns(4)
]);
6 replies
FFilament
Created by Blackpig on 5/3/2024 in #❓┊help
Build not picking up my Theme CSS
No description
2 replies
FFilament
Created by Blackpig on 2/28/2024 in #❓┊help
CheckBoxList, Enums and TextColumn display conundrum
Salut Interesting little problem. I have a Checkbox list on the form that is populated with an Enum. This all fine and works as expected - the labels are displayed and the values are stored correctly:
CheckboxList::make('type')
->label('Type')
->options(OrganisationTypes::class)
->columns(2)
->required(),
CheckboxList::make('type')
->label('Type')
->options(OrganisationTypes::class)
->columns(2)
->required(),
On the table I want to display the the selected values
TextColumn::make('type'),
TextColumn::make('type'),
Which is where the problem arises - the column displays the stored value and not the label. Because this is a multi-value field , stored as JSON in the model I need to cast it to type => 'array' If this were a simple/single value field (e.g CheckBox or Select) then I could cast it to the enum type => OrganisationTypes::class and the correct label would be displayed in the table column. So how do I cast the field to an array and still have the Enum return the correct labels in the table column? Thanks for reading this far! My enum for reference
enum OrganisationTypes: string implements HasLabel
{
case CUSTOMER = 'customer';
case SUPPLIER = 'supplier';
case MANUFACTURER = 'manufacturer';
case WAREHOUSE = 'warehouse';
case LOGISTICS = 'logictics';

public function getLabel(): ?string
{
return match ($this) {
self::CUSTOMER => 'Customer',
self::SUPPLIER => 'Supplier',
self::MANUFACTURER => 'Manufacturer',
self::WAREHOUSE => 'Warehouse',
self::LOGISTICS => 'Logistics',
default => '',
};
}
}
enum OrganisationTypes: string implements HasLabel
{
case CUSTOMER = 'customer';
case SUPPLIER = 'supplier';
case MANUFACTURER = 'manufacturer';
case WAREHOUSE = 'warehouse';
case LOGISTICS = 'logictics';

public function getLabel(): ?string
{
return match ($this) {
self::CUSTOMER => 'Customer',
self::SUPPLIER => 'Supplier',
self::MANUFACTURER => 'Manufacturer',
self::WAREHOUSE => 'Warehouse',
self::LOGISTICS => 'Logistics',
default => '',
};
}
}
8 replies
FFilament
Created by Blackpig on 1/23/2024 in #❓┊help
Reactive ->live() not updating ->helperText and/or ->label() values
Title says it all - my code below, am I missing something blindingly obvious? I'd expect the title and helper text to update on the title field when the type field changes.
return $form
->schema([
Select::make('type')
->options(MenuItemTypes::class)
->live()
->disabled(fn (?string $operation) => $operation === 'edit')
->required()
->helperText('Either add a single entry like a recipe or add mulitple options to choose from. This option can\'t be changed once set'),

Toggle::make('is_active')
->default(0),

TextInput::make('title')
->label(fn (Get $get): string => ($get('type') == MenuItemTypes::OPTIONS) ? 'Options title' : 'Title')
->helperText(fn(Get $get): ?string => ($get('type') == MenuItemTypes::OPTIONS) ? 'e.g. Choose 3 from the following options' : '')
->required()
->maxLength(255),
]);
return $form
->schema([
Select::make('type')
->options(MenuItemTypes::class)
->live()
->disabled(fn (?string $operation) => $operation === 'edit')
->required()
->helperText('Either add a single entry like a recipe or add mulitple options to choose from. This option can\'t be changed once set'),

Toggle::make('is_active')
->default(0),

TextInput::make('title')
->label(fn (Get $get): string => ($get('type') == MenuItemTypes::OPTIONS) ? 'Options title' : 'Title')
->helperText(fn(Get $get): ?string => ($get('type') == MenuItemTypes::OPTIONS) ? 'e.g. Choose 3 from the following options' : '')
->required()
->maxLength(255),
]);
19 replies
FFilament
Created by Blackpig on 1/8/2024 in #❓┊help
Nested Relation Managers - use create page not modal
Salut. I need to build a fairly complex structure which will involve nested RMs. Can I override the 'New <record>' action on the nested RM table to open in a new create/edit page rather than in a modal - so that the nested RMs will show the related records table? Rough idea of relationship structure: Top Level Model -> hasMany 2nd level model -> hasMany 3rd Level Model *-> could haveMany 4th Level Model I'm converting an existing/legacy app - so I'm pretty restricted with the data structure TIA
8 replies
FFilament
Created by Blackpig on 12/23/2023 in #❓┊help
Spatie Translatable Plugin - Repeater Fields Supported
Does the official plugin https://filamentphp.com/plugins/filament-spatie-translatable now support translation of repeater fields (stored as json).
Iirc in v2 it didn't support repeater fields so hoping v3 does
11 replies
FFilament
Created by Blackpig on 12/22/2023 in #❓┊help
Plugin v2 -> v3 upgrade - custom view page not showing header actions
My header actions are not displaying on the page. According to the docs should be auto-magic https://filamentphp.com/docs/3.x/panels/pages#adding-actions-to-pages Working my way up the inheritance the vendor/filament/filament/src/Pages/Page.php has the Concerns\InteractsWithHeaderActions; and the method is being called as I can output the returning array to ray. Am I extending the correct layout/template <x-filament-panels::page> or any thoughts as to why my actions are not displaying as expected? TIA
7 replies
FFilament
Created by Blackpig on 12/21/2023 in #❓┊help
V2 -> V3 Plugin - custom view not picking up styling
In v2 my custom view rendered fine - picking up the TW classes In v3 it's not rendering correctly. It appears that it's not picking up any additional TW classes. The blade is now extending <x-filament-panels::page> instead of <x-filament::page> Not sure what I'm missing to get the additional TW classes pulled in The view
<?php

namespace Blackpig\FilamentOffice\Resources\InvoiceResource\Pages;

use Filament\Actions\Action;
use Barryvdh\DomPDF\Facade\Pdf;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Mail;
use Filament\Notifications\Notification;
use Filament\Resources\Pages\ViewRecord;
use Blackpig\FilamentOffice\Mail\MailInvoice;
use Blackpig\FilamentOffice\Settings\OfficeSettings;
use Blackpig\FilamentOffice\Resources\InvoiceResource;

class ViewInvoice extends ViewRecord
{
protected static string $resource = InvoiceResource::class;

protected static string $view = 'filament-office::resources.invoice.view';

protected function getActions(): array
{
$actions = [
Action::make('close')
->label('Close')
->url($this->previousUrl ?? static::getResource()::getUrl())
->color('secondary'),

Action::make('pdf')
->label('Download')
->action('downloadPdf')
->color('secondary')
->icon(''),
];

if ($this->record->customer->hasEmail()) {
$actions[] = Action::make('send')
->label('Send To Customer')
->action('sendToCustomer')
->color('secondary');
}

return $actions;
}

public function downloadPdf()
{
$locale = $this->record->customer->preferred_language;
App::setLocale($locale);

$data = $this->getPdfData();
$pdf = Pdf::loadView('filament-office::resources.invoice.pdf', $data);

return response()->streamDownload(fn () => print($pdf->output()), "{$this->record->formatted_number}.pdf");
}

public function sendToCustomer()
{
$invoice = $this->record;
$locale = $invoice->customer->preferred_language;
App::setLocale($locale);

$data = $this->getPdfData();

$pdf = PDF::loadView('filament-office::resources.invoice.pdf', $data)
->setWarnings(false);

$data['site_url'] = config('app.url');

Mail::to($invoice->customer->email)
->send(new MailInvoice($data, $pdf));

Notification::make()
->title('Innvoice sent to ' . $invoice->customer->email )
->success()
->send();
}

protected function getPdfData(): array
{
return $data = [
'invoice' => $this->record,
'settings' => app(OfficeSettings::class)
];
}
}
<?php

namespace Blackpig\FilamentOffice\Resources\InvoiceResource\Pages;

use Filament\Actions\Action;
use Barryvdh\DomPDF\Facade\Pdf;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Mail;
use Filament\Notifications\Notification;
use Filament\Resources\Pages\ViewRecord;
use Blackpig\FilamentOffice\Mail\MailInvoice;
use Blackpig\FilamentOffice\Settings\OfficeSettings;
use Blackpig\FilamentOffice\Resources\InvoiceResource;

class ViewInvoice extends ViewRecord
{
protected static string $resource = InvoiceResource::class;

protected static string $view = 'filament-office::resources.invoice.view';

protected function getActions(): array
{
$actions = [
Action::make('close')
->label('Close')
->url($this->previousUrl ?? static::getResource()::getUrl())
->color('secondary'),

Action::make('pdf')
->label('Download')
->action('downloadPdf')
->color('secondary')
->icon(''),
];

if ($this->record->customer->hasEmail()) {
$actions[] = Action::make('send')
->label('Send To Customer')
->action('sendToCustomer')
->color('secondary');
}

return $actions;
}

public function downloadPdf()
{
$locale = $this->record->customer->preferred_language;
App::setLocale($locale);

$data = $this->getPdfData();
$pdf = Pdf::loadView('filament-office::resources.invoice.pdf', $data);

return response()->streamDownload(fn () => print($pdf->output()), "{$this->record->formatted_number}.pdf");
}

public function sendToCustomer()
{
$invoice = $this->record;
$locale = $invoice->customer->preferred_language;
App::setLocale($locale);

$data = $this->getPdfData();

$pdf = PDF::loadView('filament-office::resources.invoice.pdf', $data)
->setWarnings(false);

$data['site_url'] = config('app.url');

Mail::to($invoice->customer->email)
->send(new MailInvoice($data, $pdf));

Notification::make()
->title('Innvoice sent to ' . $invoice->customer->email )
->success()
->send();
}

protected function getPdfData(): array
{
return $data = [
'invoice' => $this->record,
'settings' => app(OfficeSettings::class)
];
}
}
4 replies
FFilament
Created by Blackpig on 11/16/2023 in #❓┊help
Pass value from Modal form to Action on list page
I have a form modal on a list page triggered from a header action (not a table row action). How do I grab that value in the 'ListRecords' components action? $this>pdfLanguage is empty in the action call
class ListIdeas extends ListRecords
{
protected static string $resource = IdeasResource::class;
protected static ?string $title = 'Menu Inspirations';

public string $pdfLanguage = '';

protected function getTableReorderColumn(): ?string
{
return 'position';
}

protected function getActions(): array
{
$default = parent::getActions();

$bespoke = [
Action::make('pdfLanguage')
->action('downloadPdf')
->label('Download')
->icon('heroicon-s-download')
->color('secondary')
->modalHeading('Download Menu Inspirations')
->form([
Radio::make('pdfLanguage')
->label('Which language to you want to download for: ')
->options(
[
'en' => 'English',
'fr' => 'French'
]
)
->default('en')
->inline()
->required(),
]),
];

return array_merge($bespoke, $default);
}

public function downloadPdf()
{
$data = [
$ideas = Ideas::active()->orderBy('position')->get(),
$locale = ''// how do i get handle to pdfLanguage
];

$pdf = Pdf::loadView('filament.resources.ideas.download', $data);
return response()->streamDownload(fn () => print($pdf->output()), "menu_inspirations.pdf");
}
}
class ListIdeas extends ListRecords
{
protected static string $resource = IdeasResource::class;
protected static ?string $title = 'Menu Inspirations';

public string $pdfLanguage = '';

protected function getTableReorderColumn(): ?string
{
return 'position';
}

protected function getActions(): array
{
$default = parent::getActions();

$bespoke = [
Action::make('pdfLanguage')
->action('downloadPdf')
->label('Download')
->icon('heroicon-s-download')
->color('secondary')
->modalHeading('Download Menu Inspirations')
->form([
Radio::make('pdfLanguage')
->label('Which language to you want to download for: ')
->options(
[
'en' => 'English',
'fr' => 'French'
]
)
->default('en')
->inline()
->required(),
]),
];

return array_merge($bespoke, $default);
}

public function downloadPdf()
{
$data = [
$ideas = Ideas::active()->orderBy('position')->get(),
$locale = ''// how do i get handle to pdfLanguage
];

$pdf = Pdf::loadView('filament.resources.ideas.download', $data);
return response()->streamDownload(fn () => print($pdf->output()), "menu_inspirations.pdf");
}
}
TIA
2 replies
FFilament
Created by Blackpig on 8/31/2023 in #❓┊help
V2 - Index/list page additional button next to the 'New ...' button
Title sums this up - in a V2 app I need to add an action (to open a modal) from a button placed next to the 'New <resource>' button above the table. Checked the V2 docs but not sure this is possible?
11 replies
FFilament
Created by Blackpig on 4/7/2023 in #❓┊help
Trigger page save when adding to a repeater field
Is there a hook or something that I can hook into to trigger a page/document save when clicking the 'Add to' of a repeater field?
2 replies