F
Filament17mo ago
Matthew

Display eloquent data in custom widget

How can I display User::count in a custom widget thats in the Dashboard? I cant seem to get it right, as I get Constant expression contains invalid operations error:
<?php

namespace App\Filament\App\Widgets;

use App\Models\User;
use Filament\Widgets\StatsOverviewWidget as BaseWidget;
use Filament\Widgets\StatsOverviewWidget\Stat;
use Flowframe\Trend\Trend;

class StatsOverview extends BaseWidget
{

// protected string $trend = Trend::model(User::class)->count();

// public string $count = User::count();

protected function getStats(): array
{
return [
Stat::make('Unique views', Trend::model(User::class)->count()),
];
}
}
<?php

namespace App\Filament\App\Widgets;

use App\Models\User;
use Filament\Widgets\StatsOverviewWidget as BaseWidget;
use Filament\Widgets\StatsOverviewWidget\Stat;
use Flowframe\Trend\Trend;

class StatsOverview extends BaseWidget
{

// protected string $trend = Trend::model(User::class)->count();

// public string $count = User::count();

protected function getStats(): array
{
return [
Stat::make('Unique views', Trend::model(User::class)->count()),
];
}
}
23 Replies
Patrick Boivin
Patrick Boivin17mo ago
That's right, you can't initialize class properties with function calls, you can do it in the mount() method instead
public string $name;
public string $email;

public function mount()
{
$this->name = Auth::user()->name;
$this->email = Auth::user()->email;
}
public string $name;
public string $email;

public function mount()
{
$this->name = Auth::user()->name;
$this->email = Auth::user()->email;
}
Matthew
MatthewOP17mo ago
And then what about the blade file?
Patrick Boivin
Patrick Boivin17mo ago
You'll need to modify the built-in view I think:
protected static string $view = 'my-custom-view';
protected static string $view = 'my-custom-view';
Matthew
MatthewOP17mo ago
Great! My only issue now is that polling doesnt work. Is there any reason for that?
<?php

namespace App\Filament\App\Widgets;

use App\Models\User;
use Filament\Widgets\Concerns\InteractsWithPageTable;
use Filament\Widgets\StatsOverviewWidget;
use Filament\Widgets\Widget;
use App\Models\Post;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\MarkdownEditor;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Filament\Forms\Form;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\Auth;
use Livewire\Component;
use Filament\Widgets\StatsOverviewWidget\Stat;

class UsersCount extends Widget
{
use InteractsWithPageTable;
protected static string $view = 'filament.app.widgets.users-count';
protected static ?string $pollingInterval = '2s';
protected int $count = 2;

public string $name;
public string $email;

public int $counter;
public function mount()
{
$this->name = Auth::user()->name;
$this->email = Auth::user()->email;
$this->counter = User::count();
}
}
<?php

namespace App\Filament\App\Widgets;

use App\Models\User;
use Filament\Widgets\Concerns\InteractsWithPageTable;
use Filament\Widgets\StatsOverviewWidget;
use Filament\Widgets\Widget;
use App\Models\Post;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\MarkdownEditor;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Filament\Forms\Form;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\Auth;
use Livewire\Component;
use Filament\Widgets\StatsOverviewWidget\Stat;

class UsersCount extends Widget
{
use InteractsWithPageTable;
protected static string $view = 'filament.app.widgets.users-count';
protected static ?string $pollingInterval = '2s';
protected int $count = 2;

public string $name;
public string $email;

public int $counter;
public function mount()
{
$this->name = Auth::user()->name;
$this->email = Auth::user()->email;
$this->counter = User::count();
}
}
So, I have a widget on the Dashboard and I want to display the number of users And when I create a new user, the widget doesnt update
Patrick Boivin
Patrick Boivin17mo ago
Yeah, I don't think the base Widget class has polling
Patrick Boivin
Patrick Boivin17mo ago
You may be able to add wire:poll directly in your template instead : https://livewire.laravel.com/docs/polling
Laravel
Polling | Laravel
A full-stack framework for Laravel that takes the pain out of building dynamic UIs.
Patrick Boivin
Patrick Boivin17mo ago
Oh but then I think you'll have issues with mount(), it runs only once when the page is initialized Try boot() instead if you run into any issues
Matthew
MatthewOP17mo ago
I dont get any errors There is just no polling
Patrick Boivin
Patrick Boivin17mo ago
Yes, that's because you are using the base Widget class. It doesn't have polling like the stats widgets.
Matthew
MatthewOP17mo ago
I tried with Stats Widget, but nothing
<?php

namespace App\Filament\App\Widgets;

use App\Models\User;
use Filament\Widgets\Concerns\InteractsWithPageTable;
use Filament\Widgets\StatsOverviewWidget;
use Filament\Widgets\Widget;
use App\Models\Post;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\MarkdownEditor;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Filament\Forms\Form;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\Auth;
use Livewire\Component;
use Filament\Widgets\StatsOverviewWidget\Stat;

class UsersCount extends StatsOverviewWidget
{
use InteractsWithPageTable;
protected static string $view = 'filament.app.widgets.users-count';
protected static ?string $pollingInterval = '2s';
protected int $count = 2;

public string $name;
public string $email;

public int $counter;
public function mount()
{
$this->name = Auth::user()->name;
$this->email = Auth::user()->email;
$this->counter = User::count();
}

// public function render()
// {
// return view('filament.app.widgets.users-count', [
// 'counter1' => User::count(),
// ]);
// }
}
<?php

namespace App\Filament\App\Widgets;

use App\Models\User;
use Filament\Widgets\Concerns\InteractsWithPageTable;
use Filament\Widgets\StatsOverviewWidget;
use Filament\Widgets\Widget;
use App\Models\Post;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\MarkdownEditor;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Filament\Forms\Form;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\Auth;
use Livewire\Component;
use Filament\Widgets\StatsOverviewWidget\Stat;

class UsersCount extends StatsOverviewWidget
{
use InteractsWithPageTable;
protected static string $view = 'filament.app.widgets.users-count';
protected static ?string $pollingInterval = '2s';
protected int $count = 2;

public string $name;
public string $email;

public int $counter;
public function mount()
{
$this->name = Auth::user()->name;
$this->email = Auth::user()->email;
$this->counter = User::count();
}

// public function render()
// {
// return view('filament.app.widgets.users-count', [
// 'counter1' => User::count(),
// ]);
// }
}
still no polling
Patrick Boivin
Patrick Boivin17mo ago
Please check the link I shared 👆 You can add polling yourself with a Livewire directive
Matthew
MatthewOP17mo ago
I did, but then I have an issue with render() in filament
<x-filament-widgets::widget>
<x-filament::section>
<div wire:poll>
Users: {{ $this->counter1 }}
</div>
</x-filament::section>
</x-filament-widgets::widget>
<x-filament-widgets::widget>
<x-filament::section>
<div wire:poll>
Users: {{ $this->counter1 }}
</div>
</x-filament::section>
</x-filament-widgets::widget>
Declaration of App\Filament\App\Widgets\UsersCount::render() must be compatible with Filament\Widgets\Widget::render(): Illuminate\Contracts\View\View
<?php

namespace App\Filament\App\Widgets;

use App\Models\User;
use Filament\Widgets\Concerns\InteractsWithPageTable;
use Filament\Widgets\StatsOverviewWidget;
use Filament\Widgets\Widget;
use App\Models\Post;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\MarkdownEditor;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Filament\Forms\Form;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\Auth;
use Livewire\Component;
use Filament\Widgets\StatsOverviewWidget\Stat;

class UsersCount extends Widget
{
use InteractsWithPageTable;
// protected static string $view = 'filament.app.widgets.users-count';
protected static ?string $pollingInterval = '2s';
protected int $count = 2;

public string $name;
public string $email;

public int $counter;
public function mount()
{
$this->name = Auth::user()->name;
$this->email = Auth::user()->email;
$this->counter = User::count();
}

public function render()
{
return view('filament.app.widgets.users-count', [
'counter1' => User::count(),
]);
}
}
<?php

namespace App\Filament\App\Widgets;

use App\Models\User;
use Filament\Widgets\Concerns\InteractsWithPageTable;
use Filament\Widgets\StatsOverviewWidget;
use Filament\Widgets\Widget;
use App\Models\Post;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\MarkdownEditor;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Filament\Forms\Form;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\Auth;
use Livewire\Component;
use Filament\Widgets\StatsOverviewWidget\Stat;

class UsersCount extends Widget
{
use InteractsWithPageTable;
// protected static string $view = 'filament.app.widgets.users-count';
protected static ?string $pollingInterval = '2s';
protected int $count = 2;

public string $name;
public string $email;

public int $counter;
public function mount()
{
$this->name = Auth::user()->name;
$this->email = Auth::user()->email;
$this->counter = User::count();
}

public function render()
{
return view('filament.app.widgets.users-count', [
'counter1' => User::count(),
]);
}
}
Patrick Boivin
Patrick Boivin17mo ago
Sorry but the solution is in the error message Your render() method must match the one in Widget (the return value)
Matthew
MatthewOP17mo ago
I see, all I had to do was add : View It works now. Thank you! Will check the extended classes carefully next time Solution:
<?php

namespace App\Filament\App\Widgets;

use App\Models\User;
use Filament\Widgets\Widget;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\Auth;
class UsersCount extends Widget
{
protected static ?string $pollingInterval = '2s';

public string $name;
public string $email;
public int $counter;

public function render(): View
{
return view('filament.app.widgets.users-count', [
'counter1' => User::count(),
]);
}
}
<?php

namespace App\Filament\App\Widgets;

use App\Models\User;
use Filament\Widgets\Widget;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\Auth;
class UsersCount extends Widget
{
protected static ?string $pollingInterval = '2s';

public string $name;
public string $email;
public int $counter;

public function render(): View
{
return view('filament.app.widgets.users-count', [
'counter1' => User::count(),
]);
}
}
<x-filament-widgets::widget>
<x-filament::section>
<div wire:poll>
Users: {{ $counter1 }}
</div>
</x-filament::section>
</x-filament-widgets::widget>
<x-filament-widgets::widget>
<x-filament::section>
<div wire:poll>
Users: {{ $counter1 }}
</div>
</x-filament::section>
</x-filament-widgets::widget>
Patrick Boivin
Patrick Boivin17mo ago
No worries, it trips me up too when I'm using vscode... (phpstorm has a feature that does it for you automatically)
Matthew
MatthewOP17mo ago
Uhhh, which one 😅
Matthew
MatthewOP17mo ago
Matthew
MatthewOP17mo ago
I assume the first one with the most downloads?
Patrick Boivin
Patrick Boivin17mo ago
Not extention needed, it's built-in It's built-in with phpstorm (the full editor), I don't know if it's available as a plugin for vscode
Matthew
MatthewOP17mo ago
oooo its an IDE
Matthew
MatthewOP17mo ago
Somehow all JetBrain IDE's look identical
Matthew
MatthewOP17mo ago
They work really well, but they just look ugly :/
Patrick Boivin
Patrick Boivin17mo ago
Yeah I think they all use the same UI
Want results from more Discord servers?
Add your server