Alexandre
Alexandre
FFilament
Created by Jojo on 7/2/2024 in #❓┊help
Click record without jumping
on your resource class, add this : return $table->recordUrl(null) https://filamentphp.com/docs/3.x/tables/advanced#record-urls-clickable-rows
14 replies
FFilament
Created by Alexandre on 6/13/2024 in #❓┊help
Component not found on select with native(false) and searchable()
Unfortunately not 😥 I've removed native() and searchable() but no solutions yet. I can't understand why it's only on this field that the problem occurs.
6 replies
FFilament
Created by ronssij on 6/13/2024 in #❓┊help
Shared panel session
👋 I've similar case in my project (one panel for Users and another for admin and super_admin) and I wanted to use the same login form. Here's how I did it (it may not be the best way, but it works 😅) I use the method canAccessPanel in my User Model like this :
public function canAccessPanel(Panel $panel): bool
{
if ($panel->getId() === 'admin') {
return $this->hasAnyRole(['super_admin', 'admin']);
}

if ($panel->getId() === 'user') {
return $this->hasRole(['user']);
}

return false;
}
public function canAccessPanel(Panel $panel): bool
{
if ($panel->getId() === 'admin') {
return $this->hasAnyRole(['super_admin', 'admin']);
}

if ($panel->getId() === 'user') {
return $this->hasRole(['user']);
}

return false;
}
And in my web.php route file I've made a little change for the base URL :
Route::get('/', function () {
if (Filament::auth()->check()) {
$panelRedirect = Helpers::getPanelDashboardUrlFromUser();
if ($panelRedirect != null) {
return redirect()->to($panelRedirect);
}
}

return redirect()->to('/user/login');
})->name('home');

Route::get('/admin/login', function () {
return redirect()->to('/user/login');
})->name('filament.admin.auth.login');
Route::get('/', function () {
if (Filament::auth()->check()) {
$panelRedirect = Helpers::getPanelDashboardUrlFromUser();
if ($panelRedirect != null) {
return redirect()->to($panelRedirect);
}
}

return redirect()->to('/user/login');
})->name('home');

Route::get('/admin/login', function () {
return redirect()->to('/user/login');
})->name('filament.admin.auth.login');
And I've made a little helper to manage the redirection :
public static function getPanelDashboardUrlFromUser(): ?string
{
if (Filament::auth()->check()) {

$user = Filament::auth()->user();

$panelAdmin = Filament::getPanel('admin');
$panelUser = Filament::getPanel('user');

if ($user->canAccessPanel($panelAdmin)) {
return route('filament.admin.pages.dashboard');
} elseif ($user->canAccessPanel($panelUser)) {
return route('filament.user.pages.user-dashboard');
} else {
return null;
}
}

return null;
}
public static function getPanelDashboardUrlFromUser(): ?string
{
if (Filament::auth()->check()) {

$user = Filament::auth()->user();

$panelAdmin = Filament::getPanel('admin');
$panelUser = Filament::getPanel('user');

if ($user->canAccessPanel($panelAdmin)) {
return route('filament.admin.pages.dashboard');
} elseif ($user->canAccessPanel($panelUser)) {
return route('filament.user.pages.user-dashboard');
} else {
return null;
}
}

return null;
}
So, from the same form and according to your role, you're directed to the right panel. 👍
6 replies
FFilament
Created by Alexandre on 6/10/2024 in #❓┊help
Change the default "save and create another" label in modal form
Thanks you, that it! So, what I did is put that on the getHeaderActions() method in my List resource page :
protected function getHeaderActions(): array
{
return [
Actions\CreateAction::make()
->extraModalFooterActions(fn(Action $action): array => [
$action->makeModalSubmitAction('createAnother', arguments: ['another' => true])
->label(__('marketingMessages.actions.create_another')),
]),
];
}
protected function getHeaderActions(): array
{
return [
Actions\CreateAction::make()
->extraModalFooterActions(fn(Action $action): array => [
$action->makeModalSubmitAction('createAnother', arguments: ['another' => true])
->label(__('marketingMessages.actions.create_another')),
]),
];
}
Thanks you for your help 🙂
10 replies
FFilament
Created by Alexandre on 6/10/2024 in #❓┊help
Change the default "save and create another" label in modal form
Thanks for your answer. In where method should I put this? I can't find something related in the base ListRecords.php file. I tried to use this method, but I don't think is the good one because nothing change :
protected function configureCreateAction(CreateAction|Tables\Actions\CreateAction $action): void
{
$resource = static::getResource();

$action
->authorize($resource::canCreate())
->model($this->getModel())
->modelLabel($this->getModelLabel() ?? static::getResource()::getModelLabel())
->form(fn(Form $form): Form => $this->form($form->columns(2)));

if (($action instanceof CreateAction) && static::getResource()::isScopedToTenant()) {
$action->relationship(($tenant = Filament::getTenant()) ? fn(
): Relation => static::getResource()::getTenantRelationship($tenant) : null);
}

if ($resource::hasPage('create')) {
$action->url(fn(): string => $resource::getUrl('create'));
}

// Here
if ($action instanceof CreateAction) {
$action->extraModalFooterActions(function (Action $action): array {
return [
$action->makeModalSubmitAction('createAnother', arguments: ['another' => true])
->label('My new label'),
];
});
}
}
protected function configureCreateAction(CreateAction|Tables\Actions\CreateAction $action): void
{
$resource = static::getResource();

$action
->authorize($resource::canCreate())
->model($this->getModel())
->modelLabel($this->getModelLabel() ?? static::getResource()::getModelLabel())
->form(fn(Form $form): Form => $this->form($form->columns(2)));

if (($action instanceof CreateAction) && static::getResource()::isScopedToTenant()) {
$action->relationship(($tenant = Filament::getTenant()) ? fn(
): Relation => static::getResource()::getTenantRelationship($tenant) : null);
}

if ($resource::hasPage('create')) {
$action->url(fn(): string => $resource::getUrl('create'));
}

// Here
if ($action instanceof CreateAction) {
$action->extraModalFooterActions(function (Action $action): array {
return [
$action->makeModalSubmitAction('createAnother', arguments: ['another' => true])
->label('My new label'),
];
});
}
}
10 replies
FFilament
Created by Alexandre on 5/27/2024 in #❓┊help
Wizard Form display a modal after submit instead a redirect
Perfect, I've found it 🥳 If anyone is looking to do the same, here's how I did it: Go to vendor/filament/filament/resources/views/resources/pages/create-record.blade.php and copy the contents. Create a new blade page in your view folder and paste the content you've just copied. In this page, add your modal :
<x-filament-panels::page
@class([
'fi-resource-create-record-page',
'fi-resource-' . str_replace('/', '-', $this->getResource()::getSlug()),
])
>

<x-filament-panels::form
id="form"
:wire:key="$this->getId() . '.forms.' . $this->getFormStatePath()"
wire:submit="create"
>
{{ $this->form }}

<x-filament-panels::form.actions
:actions="$this->getCachedFormActions()"
:full-width="$this->hasFullWidthFormActions()"
/>
</x-filament-panels::form>
//modal here !
<x-filament-panels::page.unsaved-data-changes-alert/>
<x-filament::modal id="modal-id">
<p>My modal</p>
</x-filament::modal>

</x-filament-panels::page>
<x-filament-panels::page
@class([
'fi-resource-create-record-page',
'fi-resource-' . str_replace('/', '-', $this->getResource()::getSlug()),
])
>

<x-filament-panels::form
id="form"
:wire:key="$this->getId() . '.forms.' . $this->getFormStatePath()"
wire:submit="create"
>
{{ $this->form }}

<x-filament-panels::form.actions
:actions="$this->getCachedFormActions()"
:full-width="$this->hasFullWidthFormActions()"
/>
</x-filament-panels::form>
//modal here !
<x-filament-panels::page.unsaved-data-changes-alert/>
<x-filament::modal id="modal-id">
<p>My modal</p>
</x-filament::modal>

</x-filament-panels::page>
After that, on your create function in CreateRequest.php, just pass the event to open the modal and that it !
public function create(bool $another = false): void
{
//create logic

$this->dispatch('open-modal', id: 'modal-confirmation');
}
public function create(bool $another = false): void
{
//create logic

$this->dispatch('open-modal', id: 'modal-confirmation');
}
FilamentPHP is so much fun to use and even more fun to learn, I love it, and thanks for that! 🤩
5 replies
FFilament
Created by Alexandre on 5/27/2024 in #❓┊help
Wizard Form display a modal after submit instead a redirect
Well, I may have an idea, but it's not that yet. I redid the create() function in my CreateRequest.php I copy/pasted all the methods and then removed this part:
$redirectUrl = $this->getRedirectUrl();
$this->redirect($redirectUrl, navigate: FilamentView::hasSpaMode() && is_app_url($redirectUrl));
$redirectUrl = $this->getRedirectUrl();
$this->redirect($redirectUrl, navigate: FilamentView::hasSpaMode() && is_app_url($redirectUrl));
Originally, I wanted to put an Action() on it, but when I clicked on the button, nothing happened and the action didn't open (no error in the console). So I was wondering, is it possible to create a view with the contents of the modal with the Blade component <x-filament::modal/> and call it in the create method with this (instead of the redirect):
$this->dispatch('open-modal', id: 'modal-confirmation');
$this->dispatch('open-modal', id: 'modal-confirmation');
If this is possible, how do I add the view Blade component to the "CreateRequest" page of my resource? A method in mount()? Thanks in advance 🙂
5 replies
FFilament
Created by Alexandre on 5/22/2024 in #❓┊help
$get() in Wizard Form is null
Aaaaahh okay, it happens even to the best. All is good now. Thanks, I will use it, didn't know that helper! 😇
13 replies
FFilament
Created by Alexandre on 5/22/2024 in #❓┊help
$get() in Wizard Form is null
$livewire->data['building'] return the ID of the option selected in the select building field (on step 1). For example, 168.
13 replies
FFilament
Created by Alexandre on 5/22/2024 in #❓┊help
$get() in Wizard Form is null
That's all right then, because you can't go on to step 2 if the "building" field is empty 👍 However, the data_get returns null and I'm having a bit of trouble understanding why... Knowing that $livewire->data['building'] does return a result. I guess it's having trouble finding the 'building' field but I've tried with '../' and '../../' and it doesn't make any difference. However, as expressed in my first message, I just have 2 steps with a repeater in the second. I'm tempted to say that it's not too bad as long as $livewire->data is ok, but uh 🤷‍♂️
13 replies
FFilament
Created by Alexandre on 5/22/2024 in #❓┊help
$get() in Wizard Form is null
Thanks for your feedback. The docs specify that $get is scoped in the repeater when used inside. When I do a dd($get), I only get the select input in the second step, but not all fields. $livewire->data return an array with all fields and their values. If I do data_get('building', $livewire->data, ''); I've got an empty string in return. Same with data_get('building', $livewire->data['building'], ''); and data_get('../building', $livewire->data['building'], ''); I guess using $building_id = $livewire->data['building']; is valid?
13 replies
FFilament
Created by Alexandre on 5/22/2024 in #❓┊help
$get() in Wizard Form is null
I found another way, but I don't know if it's a good one 🙃
So... I'd like your opinion. I use the Livewire component to retrieve the field value and perform the search. The result is as follows:
->getSearchResultsUsing(function (
string $search,
Livewire $livewire
): array {
$building_id = $livewire->data['building'];

return Media::where('model_type',
'App\Models\building')->where('model_id',
$building_id)
->where('name',
'like', "%{$search}%")
->limit(50)
->pluck('name', 'id')
->toArray();
})
->getSearchResultsUsing(function (
string $search,
Livewire $livewire
): array {
$building_id = $livewire->data['building'];

return Media::where('model_type',
'App\Models\building')->where('model_id',
$building_id)
->where('name',
'like', "%{$search}%")
->limit(50)
->pluck('name', 'id')
->toArray();
})
And… It's work. Seem ok?
13 replies
FFilament
Created by Alexandre on 5/22/2024 in #❓┊help
$get() in Wizard Form is null
Ok, I found that : https://filamentphp.com/docs/3.x/forms/fields/repeater#using-get-to-access-parent-field-values So, I try to use this : dd($get('../building')); (with one "../", two and three) but same result. Is there a way to DD the form structure?
13 replies
FFilament
Created by Alexandre on 5/15/2024 in #❓┊help
Is it possible to format a new option created in a Select?
Hello all, I finally figured out how to do it after a lot of research 😅 So, for my case I can use the getOptionLabelUsing method
->getOptionLabelUsing(function ($value) {
$building = Building::find($value);

if ($building) {
return "<strong>{$building->name}</strong> - {$building->number}, {$building->street} | {$building->postal_code} {$building->city} ({$building->country})";
}

return $value;

})
->getOptionLabelUsing(function ($value) {
$building = Building::find($value);

if ($building) {
return "<strong>{$building->name}</strong> - {$building->number}, {$building->street} | {$building->postal_code} {$building->city} ({$building->country})";
}

return $value;

})
$value is the value of the selected option (= the ID model) And there is it 🥳
3 replies
FFilament
Created by Alexandre on 5/7/2024 in #❓┊help
Handle the creation process for a wizard form
Ah ok, I feel like an idiot... 🫥 Well, problem solved 😎
Thanks a lot for your time!
8 replies
FFilament
Created by Alexandre on 5/7/2024 in #❓┊help
Handle the creation process for a wizard form
Ah uh, sorry... When I mentioned my resource file, I meant the one at the root of app/Filament (in my case: RequestResource.php). I use the standard form() function.
public static function form(Form $form): Form {
return $form
->schema([
Wizard::make([ ...]);
->submitAction(new HtmlString(Blade::render(<<<BLADE
<x-filament::button
type="submit"
size="sm"
>
Submit
</x-filament::button>
BLADE
)))
]);
}

protected function handleRecordCreation(array $data): Model {
dd($data);
}
public static function form(Form $form): Form {
return $form
->schema([
Wizard::make([ ...]);
->submitAction(new HtmlString(Blade::render(<<<BLADE
<x-filament::button
type="submit"
size="sm"
>
Submit
</x-filament::button>
BLADE
)))
]);
}

protected function handleRecordCreation(array $data): Model {
dd($data);
}
8 replies
FFilament
Created by Alexandre on 5/3/2024 in #❓┊help
Header action on section to go back on a specific step on a Wizard Form
Yup of course you can 👍
10 replies
FFilament
Created by Alexandre on 5/3/2024 in #❓┊help
Header action on section to go back on a specific step on a Wizard Form
Thanks to both of you for your response and follow-up 😇 @PovilasKorop I know that the buttons in the header are clickable and that we have the previous/next buttons. But, for the header buttons, I know that not everyone is likely to understand that it's clickable. In my case, the request is to have an additional "Summary" step that summarizes the answers from the previous steps, with a "Edit" button that takes you back to the step where the fields are. Following @ben9563 's reply, here's what I did: In my last step and for each step I made a Section which contains the answers of the step. Something like this:
Section::make('Bâtiment')
->description('Identification du bâtiment')
->icon('heroicon-m-building-office')
->schema([
//Contains step responses in Placeholder format
])
Section::make('Bâtiment')
->description('Identification du bâtiment')
->icon('heroicon-m-building-office')
->schema([
//Contains step responses in Placeholder format
])
I then added an Action in the header with a particular view where I pass the step ID:
Section::make('Bâtiment')
->description('Identification du bâtiment')
->icon('heroicon-m-building-office')
->schema([
//Contains step responses in Placeholder format
])
->headerActions([
Action::make('Modifier')->view('filament.user.actions.modify-step', ['step' => '01-batiment']),
])
Section::make('Bâtiment')
->description('Identification du bâtiment')
->icon('heroicon-m-building-office')
->schema([
//Contains step responses in Placeholder format
])
->headerActions([
Action::make('Modifier')->view('filament.user.actions.modify-step', ['step' => '01-batiment']),
])
Then I create a Filament button with Alpine's click method to trigger the step change:
<x-filament::button
x-on:click="step = '{{$step}}'"
icon="heroicon-m-pencil-square"
>
Edit
</x-filament::button>
<x-filament::button
x-on:click="step = '{{$step}}'"
icon="heroicon-m-pencil-square"
>
Edit
</x-filament::button>
Voilà, voilà, just like that, everything works. Thanks again 😃
10 replies
FFilament
Created by developer on 4/10/2024 in #❓┊help
user dropdown broke after update to latest version
I've the same problem after upgrade, just run
npm run build
npm run build
resolve the issue for me
36 replies
FFilament
Created by Alexandre on 3/27/2024 in #❓┊help
How to put the resource creation link in the navigation of the panel?
Hey, great it's working thanks ! But it's weird because the active class was also set to the "All requests" item (generated via the RequestResource" class). So I added this to RequestResource.php:
protected static bool $shouldRegisterNavigation = false;
protected static bool $shouldRegisterNavigation = false;
And add a new Item in my navigation for the ListRequest :
->navigationItems(
[
NavigationItem::make( 'New request' )
->label( __( 'users/requests.create.navigation_label' ) )
->group( __( 'users/requests.navigation_group' ) )
->url(fn () => CreateRequest::getUrl())
->icon( 'heroicon-o-plus' )
->isActiveWhen(fn () => request()->routeIs(CreateRequest::getRouteName())),
NavigationItem::make( 'See requests' )
->label( __( 'users/requests.all.navigation_label' ) )
->group( __( 'users/requests.navigation_group' ) )
->url(fn () => ListRequests::getUrl())
->icon( 'heroicon-o-eye' )
->isActiveWhen(fn () => request()->routeIs(ListRequests::getRouteName())),
]
)
->navigationItems(
[
NavigationItem::make( 'New request' )
->label( __( 'users/requests.create.navigation_label' ) )
->group( __( 'users/requests.navigation_group' ) )
->url(fn () => CreateRequest::getUrl())
->icon( 'heroicon-o-plus' )
->isActiveWhen(fn () => request()->routeIs(CreateRequest::getRouteName())),
NavigationItem::make( 'See requests' )
->label( __( 'users/requests.all.navigation_label' ) )
->group( __( 'users/requests.navigation_group' ) )
->url(fn () => ListRequests::getUrl())
->icon( 'heroicon-o-eye' )
->isActiveWhen(fn () => request()->routeIs(ListRequests::getRouteName())),
]
)
So now it's good. Thanks for your help 😃
5 replies