Custom Page Table Actions Help - still broken
I have a custom page the table is showing fine however when I click on the action nothing is happening, it should be dumping the record.
The end goal of this action is to run this query inside the action itself
However clicking on the action displays/does nothing itself, I tested the action on an actual resource and it works.
UserTranslation::query()
->where('user_id', $record->user_id)
->update(['is_paid' => true]);
UserTranslation::query()
->where('user_id', $record->user_id)
->update(['is_paid' => true]);
<?php
namespace Kenepa\TranslationManager\Pages;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Filament\Notifications\Notification;
use Filament\Resources\Pages\Page;
use Filament\Tables\Actions\Action;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Concerns\InteractsWithTable;
use Filament\Tables\Contracts\HasTable;
use Filament\Tables\Table;
use Illuminate\Contracts\View\View;
use Illuminate\Database\Query\Builder;
use Illuminate\Support\Facades\DB;
use Kenepa\TranslationManager\Models\UserTranslation;
use Kenepa\TranslationManager\Resources\LanguageLineResource;
use Kenepa\TranslationManager\Traits\CanRegisterPanelNavigation;
class TranslationBilling extends Page implements HasForms, HasTable
{
use CanRegisterPanelNavigation;
use InteractsWithTable;
use InteractsWithForms;
protected static ?string $navigationIcon = 'heroicon-o-document-text';
// protected static ?string $navigationGroup = 'MyNavigationGroup';
protected static string $view = 'translation-manager::translation-billing';
protected static string $resource = LanguageLineResource::class;
public static function shouldRegisterNavigation(array $parameters = []): bool
{
return static::shouldRegisterOnPanel() ? config('translation-manager.quick_translate_navigation_registration') : false;
}
public static function getNavigationGroup(): ?string
{
return config('translation-manager.navigation_group');
}
public static function getNavigationIcon(): ?string
{
return 'heroicon-o-currency-dollar';
}
public function mount(): void
{
abort_unless(static::shouldRegisterOnPanel(), 403);
}
public function getTableRecordKey($record): string
{
return (string) $record->getKeyName();
}
public function table(Table $table): Table
{
return $table
->query(
UserTranslation::query()
->select('user_id', DB::raw('SUM(word_count) as total_word_count'))
->where('is_paid', false)
->groupBy('user_id')
->orderBy('total_word_count', 'desc')
)
->columns([
TextColumn::make('user.name')
->searchable(),
TextColumn::make('total_word_count')
->sortable(),
])
->filters([
// ...
])
->actions([
Action::make('mark_paid')
->label('Mark Paid')
->icon('heroicon-o-currency-dollar')
->color('success')
->before(function ($record) {
dd('hello');
})
->action(function ($record) {
dd($record);
})
->after(function(){
Notification::make()
->duration(3000)
->success()
->title('User Paid')
->body('User has been marked as paid.')
->send();
})
])
->bulkActions([
// ...
]);
}
}
<?php
namespace Kenepa\TranslationManager\Pages;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Filament\Notifications\Notification;
use Filament\Resources\Pages\Page;
use Filament\Tables\Actions\Action;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Concerns\InteractsWithTable;
use Filament\Tables\Contracts\HasTable;
use Filament\Tables\Table;
use Illuminate\Contracts\View\View;
use Illuminate\Database\Query\Builder;
use Illuminate\Support\Facades\DB;
use Kenepa\TranslationManager\Models\UserTranslation;
use Kenepa\TranslationManager\Resources\LanguageLineResource;
use Kenepa\TranslationManager\Traits\CanRegisterPanelNavigation;
class TranslationBilling extends Page implements HasForms, HasTable
{
use CanRegisterPanelNavigation;
use InteractsWithTable;
use InteractsWithForms;
protected static ?string $navigationIcon = 'heroicon-o-document-text';
// protected static ?string $navigationGroup = 'MyNavigationGroup';
protected static string $view = 'translation-manager::translation-billing';
protected static string $resource = LanguageLineResource::class;
public static function shouldRegisterNavigation(array $parameters = []): bool
{
return static::shouldRegisterOnPanel() ? config('translation-manager.quick_translate_navigation_registration') : false;
}
public static function getNavigationGroup(): ?string
{
return config('translation-manager.navigation_group');
}
public static function getNavigationIcon(): ?string
{
return 'heroicon-o-currency-dollar';
}
public function mount(): void
{
abort_unless(static::shouldRegisterOnPanel(), 403);
}
public function getTableRecordKey($record): string
{
return (string) $record->getKeyName();
}
public function table(Table $table): Table
{
return $table
->query(
UserTranslation::query()
->select('user_id', DB::raw('SUM(word_count) as total_word_count'))
->where('is_paid', false)
->groupBy('user_id')
->orderBy('total_word_count', 'desc')
)
->columns([
TextColumn::make('user.name')
->searchable(),
TextColumn::make('total_word_count')
->sortable(),
])
->filters([
// ...
])
->actions([
Action::make('mark_paid')
->label('Mark Paid')
->icon('heroicon-o-currency-dollar')
->color('success')
->before(function ($record) {
dd('hello');
})
->action(function ($record) {
dd($record);
})
->after(function(){
Notification::make()
->duration(3000)
->success()
->title('User Paid')
->body('User has been marked as paid.')
->send();
})
])
->bulkActions([
// ...
]);
}
}
15 Replies
did you add
<x-filament-actions::modals />
@Lara Zeus this is my view
The weird thing is the action works on any resource just not a custom page
<x-filament-panels::page>
<x-filament-actions::modals />
<div>
{{ $this->table }}
</div>
</x-filament-panels::page>
<x-filament-panels::page>
<x-filament-actions::modals />
<div>
{{ $this->table }}
</div>
</x-filament-panels::page>
Try setting ->query() to just the base query. The select(), groupBy(), etc should be in ->modifyQueryUsing()
The Page class also, already has the HasForms and HasActions interfaces and traits. Maybe including those on your page is interfering with something.
@awcodes i tried that aswell just to bring everything to basics
the action just doesn't seem to be executing at all. I added a delete action in there as well just to test but nothing happens when I click that either.
public function table(Table $table): Table
{
return $table
->query(fn (Builder $query) => UserTranslation::query())
->columns([
TextColumn::make('user.name')
->searchable(),
TextColumn::make('total_word_count')
->sortable(),
])
->filters([
// ...
])
->actions([
Action::make('delete')
->action(fn () => $this->record->delete()),
Action::make('mark_paid')
->label('Mark Paid')
->icon('heroicon-o-currency-dollar')
->color('success')
->before(function ($record) {
dd('hello');
})
->action(function ($record) {
UserTranslation::query()
->where('user_id', $record->user_id)
->update(['is_paid' => true]);
})
->after(function(){
Notification::make()
->duration(3000)
->success()
->title('User Paid')
->body('User has been marked as paid.')
->send();
})
])
->bulkActions([
// ...
]);
}
public function table(Table $table): Table
{
return $table
->query(fn (Builder $query) => UserTranslation::query())
->columns([
TextColumn::make('user.name')
->searchable(),
TextColumn::make('total_word_count')
->sortable(),
])
->filters([
// ...
])
->actions([
Action::make('delete')
->action(fn () => $this->record->delete()),
Action::make('mark_paid')
->label('Mark Paid')
->icon('heroicon-o-currency-dollar')
->color('success')
->before(function ($record) {
dd('hello');
})
->action(function ($record) {
UserTranslation::query()
->where('user_id', $record->user_id)
->update(['is_paid' => true]);
})
->after(function(){
Notification::make()
->duration(3000)
->success()
->title('User Paid')
->body('User has been marked as paid.')
->send();
})
])
->bulkActions([
// ...
]);
}
You’re extending Page, right? But page doesn’t implement HasTables or uses InteractsWithTables. It’s also possible you’re using the wrong action class in your table’s ->actions() callback. Just kind of guessing here since I can’t see all of the code.
<?php
namespace Kenepa\TranslationManager\Pages;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Filament\Notifications\Notification;
use Filament\Pages\Page;
use Filament\Tables\Actions\Action;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Concerns\InteractsWithTable;
use Filament\Tables\Contracts\HasTable;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Database\Query\Builder;
use Kenepa\TranslationManager\Models\UserTranslation;
use Kenepa\TranslationManager\Resources\LanguageLineResource;
use Kenepa\TranslationManager\Traits\CanRegisterPanelNavigation;
class TranslationBilling extends Page implements HasForms, HasTable
{
use CanRegisterPanelNavigation;
use InteractsWithTable;
use InteractsWithForms;
// protected static ?string $cluster = Translations::class;
protected static ?string $navigationIcon = 'heroicon-o-document-text';
protected static ?string $navigationGroup ='Translations';
protected static string $view = 'translation-manager::translation-billing';
public static function canAccess(array $parameters = []): bool
{
return auth()->user()->hasPermissionTo('manage-translation-billing');
}
public static function shouldRegisterNavigation(array $parameters = []): bool
{
return static::shouldRegisterOnPanel() ? config('translation-manager.quick_translate_navigation_registration') : false;
}
public static function getNavigationGroup(): ?string
{
return config('translation-manager.navigation_group');
}
public static function getNavigationIcon(): ?string
{
return 'heroicon-o-currency-dollar';
}
public function mount(): void
{
abort_unless(static::shouldRegisterOnPanel(), 403);
}
public function getTableRecordKey($record): string
{
return (string) $record->getKeyName();
}
public function tableQuery(): \Illuminate\Database\Eloquent\Builder|Relation|null
{
return UserTranslation::query();
// ->select('user_id', DB::raw('SUM(word_count) as total_word_count'))
// ->where('is_paid', false)
// ->groupBy('user_id')
// ->orderBy('total_word_count', 'desc');
}
public function getHeaderWidgets(): array
{
return [
LanguageLineResource\Widgets\TotalTranslationsRequired::class
];
}
public function table(Table $table): Table
{
return $table
->query(fn (Builder $query) => UserTranslation::query())
->columns([
TextColumn::make('user.name')
->searchable(),
TextColumn::make('total_word_count')
->sortable(),
])
->filters([
// ...
])
->actions([
Action::make('delete')
->action(fn () => $this->record->delete()),
Action::make('mark_paid')
->label('Mark Paid')
->icon('heroicon-o-currency-dollar')
->color('success')
->before(function ($record) {
dd('hello');
})
->action(function ($record) {
UserTranslation::query()
->where('user_id', $record->user_id)
->update(['is_paid' => true]);
})
->after(function(){
Notification::make()
->duration(3000)
->success()
->title('User Paid')
->body('User has been marked as paid.')
->send();
})
])
->bulkActions([
// ...
]);
}
}
<?php
namespace Kenepa\TranslationManager\Pages;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Filament\Notifications\Notification;
use Filament\Pages\Page;
use Filament\Tables\Actions\Action;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Concerns\InteractsWithTable;
use Filament\Tables\Contracts\HasTable;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Database\Query\Builder;
use Kenepa\TranslationManager\Models\UserTranslation;
use Kenepa\TranslationManager\Resources\LanguageLineResource;
use Kenepa\TranslationManager\Traits\CanRegisterPanelNavigation;
class TranslationBilling extends Page implements HasForms, HasTable
{
use CanRegisterPanelNavigation;
use InteractsWithTable;
use InteractsWithForms;
// protected static ?string $cluster = Translations::class;
protected static ?string $navigationIcon = 'heroicon-o-document-text';
protected static ?string $navigationGroup ='Translations';
protected static string $view = 'translation-manager::translation-billing';
public static function canAccess(array $parameters = []): bool
{
return auth()->user()->hasPermissionTo('manage-translation-billing');
}
public static function shouldRegisterNavigation(array $parameters = []): bool
{
return static::shouldRegisterOnPanel() ? config('translation-manager.quick_translate_navigation_registration') : false;
}
public static function getNavigationGroup(): ?string
{
return config('translation-manager.navigation_group');
}
public static function getNavigationIcon(): ?string
{
return 'heroicon-o-currency-dollar';
}
public function mount(): void
{
abort_unless(static::shouldRegisterOnPanel(), 403);
}
public function getTableRecordKey($record): string
{
return (string) $record->getKeyName();
}
public function tableQuery(): \Illuminate\Database\Eloquent\Builder|Relation|null
{
return UserTranslation::query();
// ->select('user_id', DB::raw('SUM(word_count) as total_word_count'))
// ->where('is_paid', false)
// ->groupBy('user_id')
// ->orderBy('total_word_count', 'desc');
}
public function getHeaderWidgets(): array
{
return [
LanguageLineResource\Widgets\TotalTranslationsRequired::class
];
}
public function table(Table $table): Table
{
return $table
->query(fn (Builder $query) => UserTranslation::query())
->columns([
TextColumn::make('user.name')
->searchable(),
TextColumn::make('total_word_count')
->sortable(),
])
->filters([
// ...
])
->actions([
Action::make('delete')
->action(fn () => $this->record->delete()),
Action::make('mark_paid')
->label('Mark Paid')
->icon('heroicon-o-currency-dollar')
->color('success')
->before(function ($record) {
dd('hello');
})
->action(function ($record) {
UserTranslation::query()
->where('user_id', $record->user_id)
->update(['is_paid' => true]);
})
->after(function(){
Notification::make()
->duration(3000)
->success()
->title('User Paid')
->body('User has been marked as paid.')
->send();
})
])
->bulkActions([
// ...
]);
}
}
You need to call
parent::mount()
in your mount function since you are overriding it.<?php
namespace IllusiveCh\FilamentTranslationManager\Pages;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Filament\Notifications\Notification;
use Filament\Pages\Page;
use Filament\Tables\Actions\Action;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Concerns\InteractsWithTable;
use Filament\Tables\Contracts\HasTable;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Database\Query\Builder;
use Illuminate\Support\Facades\DB;
use IllusiveCh\FilamentTranslationManager\Models\UserTranslation;
use IllusiveCh\FilamentTranslationManager\Resources\LanguageLineResource;
use IllusiveCh\FilamentTranslationManager\Traits\CanRegisterPanelNavigation;
class TranslationBilling extends Page implements HasForms, HasTable
{
use CanRegisterPanelNavigation;
use InteractsWithTable;
use InteractsWithForms;
// protected static ?string $cluster = Translations::class;
protected static ?string $navigationIcon = 'heroicon-o-document-text';
protected static ?string $navigationGroup ='Translations';
protected static string $view = 'translation-manager::translation-billing';
public static function canAccess(array $parameters = []): bool
{
return auth()->user()->hasPermissionTo('manage-translation-billing');
}
public static function shouldRegisterNavigation(array $parameters = []): bool
{
return static::shouldRegisterOnPanel() ? config('translation-manager.quick_translate_navigation_registration') : false;
}
public static function getNavigationGroup(): ?string
{
return config('translation-manager.navigation_group');
}
public static function getNavigationIcon(): ?string
{
return 'heroicon-o-currency-dollar';
}
public function getTableRecordKey($record): string
{
return (string) $record->getKeyName();
}
public function tableQuery(): \Illuminate\Database\Eloquent\Builder|Relation|null
{
return UserTranslation::query()
->select('user_id', DB::raw('SUM(word_count) as total_word_count'))
->where('is_paid', false)
->groupBy('user_id')
->orderBy('total_word_count', 'desc');
}
public function getHeaderWidgets(): array
{
return [
LanguageLineResource\Widgets\TotalTranslationsRequired::class
];
}
public function table(Table $table): Table
{
return $table
->query(fn (Builder $query) => $this->tableQuery())
->columns([
TextColumn::make('user.name')
->searchable(),
TextColumn::make('total_word_count')
->sortable(),
])
->filters([
// ...
])
->actions([
Action::make('delete')
->action(fn () => $this->record->delete()),
Action::make('mark_paid')
->label('Mark Paid')
->icon('heroicon-o-currency-dollar')
->color('success')
->before(function ($record) {
dd('here');
})
->action(function ($record) {
UserTranslation::query()
->where('user_id', $record->user_id)
->update(['is_paid' => true]);
})
->after(function(){
Notification::make()
->duration(3000)
->success()
->title('User Paid')
->body('User has been marked as paid.')
->send();
})
])
->bulkActions([
// ...
]);
}
}
<?php
namespace IllusiveCh\FilamentTranslationManager\Pages;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Filament\Notifications\Notification;
use Filament\Pages\Page;
use Filament\Tables\Actions\Action;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Concerns\InteractsWithTable;
use Filament\Tables\Contracts\HasTable;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Database\Query\Builder;
use Illuminate\Support\Facades\DB;
use IllusiveCh\FilamentTranslationManager\Models\UserTranslation;
use IllusiveCh\FilamentTranslationManager\Resources\LanguageLineResource;
use IllusiveCh\FilamentTranslationManager\Traits\CanRegisterPanelNavigation;
class TranslationBilling extends Page implements HasForms, HasTable
{
use CanRegisterPanelNavigation;
use InteractsWithTable;
use InteractsWithForms;
// protected static ?string $cluster = Translations::class;
protected static ?string $navigationIcon = 'heroicon-o-document-text';
protected static ?string $navigationGroup ='Translations';
protected static string $view = 'translation-manager::translation-billing';
public static function canAccess(array $parameters = []): bool
{
return auth()->user()->hasPermissionTo('manage-translation-billing');
}
public static function shouldRegisterNavigation(array $parameters = []): bool
{
return static::shouldRegisterOnPanel() ? config('translation-manager.quick_translate_navigation_registration') : false;
}
public static function getNavigationGroup(): ?string
{
return config('translation-manager.navigation_group');
}
public static function getNavigationIcon(): ?string
{
return 'heroicon-o-currency-dollar';
}
public function getTableRecordKey($record): string
{
return (string) $record->getKeyName();
}
public function tableQuery(): \Illuminate\Database\Eloquent\Builder|Relation|null
{
return UserTranslation::query()
->select('user_id', DB::raw('SUM(word_count) as total_word_count'))
->where('is_paid', false)
->groupBy('user_id')
->orderBy('total_word_count', 'desc');
}
public function getHeaderWidgets(): array
{
return [
LanguageLineResource\Widgets\TotalTranslationsRequired::class
];
}
public function table(Table $table): Table
{
return $table
->query(fn (Builder $query) => $this->tableQuery())
->columns([
TextColumn::make('user.name')
->searchable(),
TextColumn::make('total_word_count')
->sortable(),
])
->filters([
// ...
])
->actions([
Action::make('delete')
->action(fn () => $this->record->delete()),
Action::make('mark_paid')
->label('Mark Paid')
->icon('heroicon-o-currency-dollar')
->color('success')
->before(function ($record) {
dd('here');
})
->action(function ($record) {
UserTranslation::query()
->where('user_id', $record->user_id)
->update(['is_paid' => true]);
})
->after(function(){
Notification::make()
->duration(3000)
->success()
->title('User Paid')
->body('User has been marked as paid.')
->send();
})
])
->bulkActions([
// ...
]);
}
}
Try a different name for the action. I’m wondering if it’s conflicting with another cached action.
Also maybe drop the interactsWithForms, doubt that’s a problem but you should only need that if you have a form on the page too.
I have updated the code with a new action name, Inspecting console I can see the request being posted but the mountedActions array response seems to be empty which may be weird??
The code I’ve seen looks fine to me. Hard to say what is going on without seeing the whole codebase at this point.
i can put that action on any table and it seems to work fine, just not a custom page
I hear ya, but there’s something else missing and without being able to actually interact with the code I’m at a loss as to what the problem might actually be. I’m using table actions just fine on custom pages. So something else is going on somewhere else in your app that I just can’t see from the code that has been shared.
sounds good, atleast I know the code is correct ill try to hunt down elsewhere it could be.
@datarecall , did you figured it out? I'm facing the same behaviour when trying to call a table action from a custom component table.
Ok, i got it working for my use case.
I was declaring the table->query() to a relation query, just replacing it by table->relationship(...) made it work.