#Dynamic sidebar

13 messages · Page 1 of 1 (latest)

rain rune
#

I'm using Filament 3 and want the sidebar to include a "Channels" group with dynamic items loaded from the database (one per active channel of the authenticated user). The rest of the navigation should still work via discoverResources().

The problem is that I can’t access auth()->user() inside panel() because the user isn’t authenticated yet, so I can’t generate those items there.

Is there any recommended way to add user-specific dynamic items without breaking the default discovery and without overriding everything with navigationItems()?

Thanks!

lilac creekBOT
#

To help others find answers, you can mark your question as solved via Right click solution message -> Apps -> ✅ Mark Solution

warm wing
#

For that sir you need a middleware to do it 😉

#

similar to attached

<?php

namespace App\Http\Middleware;

use Closure;
use Filament\Navigation\NavigationItem;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class TenantCheck
{
    /**
     * Handle an incoming request.
     *
     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
     */
    public function handle(Request $request, Closure $next): Response
    {

        $filamentTenant = \Filament\Facades\Filament::getTenant();

        if ($menuItems = $filamentTenant->customNavLinks) {
            $panel = \Filament\Facades\Filament::getPanel();

            $mItems = [];

            foreach ($menuItems as $menuItem) {
                $mItems[] =
                        NavigationItem::make($menuItem->label)
                            ->group($menuItem->group ?? null)
                            ->visible(auth()->user()->can('view', $menuItem))
                            ->url($menuItem->url)
                            ->icon($menuItem->icon ?? null)
                            ->openUrlInNewTab($menuItem->new_window ?? false);
            }
        }

        if (! empty($mItems)) {
            $panel->navigationItems($mItems);
        }

        return $next($request);
    }
}

customNavLinks is a relationship to a custom table.

rain rune
#

thanks @warm wing I try this solution but Filament:getTenant() it's null. I put middleware on Panel Provider ->authMiddleware()

warm wing
#

Hmm I am sure it gets hit eventually, I did see a current_tenant_id on the user model on my instant and used that to get the tenant

rain rune
#

Using your idea, I was able to insert the channels into navigation items, but they are not visible in the side menu.

<?php

namespace App\Http\Middleware;

use App\Models\Channel;
use Closure;
use Filament\Facades\Filament;
use Filament\Navigation\NavigationItem;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class TenantCheckMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param Closure(Request): (Response) $next
     */
    public function handle(Request $request, Closure $next): Response
    {
        $panel = Filament::getPanel();

        $menuItems = Channel::query()->where('user_id', auth()->id())->get();

        foreach ($menuItems as $menuItem) {
            $mItems[] =
                NavigationItem::make($menuItem->identifier)
                    ->group('Channels');
        }

        if (!empty($mItems)) {
            $panel->navigationItems($mItems);
        }

        return $next($request);
    }
}
rain rune
#

I add this on UserPanelProvider and it doesn't works... navigation items does not show

->navigationGroups([
      NavigationGroup::make()
          ->label('Channel')
          ->icon('heroicon-o-shopping-cart'),
  ])
rain rune
#

I have already been able to get your code @warm wing to work with the tenant (it should have been in tenantMiddleware()), but I still can't get the dynamic items to come out 😦

rain rune
#

I finally found the solution. I used ServiceProvider instead of Middleware, and it worked perfectly.

Here's the code.

<?php

namespace App\Providers;

use Filament\Events\TenantSet;
use Filament\Facades\Filament;
use Filament\Navigation\NavigationItem;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\ServiceProvider;

class TenantNavigationServiceProvider extends ServiceProvider
{
    public function register(): void
    {

    }

    public function boot(): void
    {
        Event::listen(TenantSet::class, function (TenantSet $event) {
            $tenant = $event->getTenant();
            $panel = Filament::getPanel('user');


            if ($tenant && $tenant->channels) {
                $navigationItems = [];

                foreach ($tenant->channels as $channel) {
                    $navigationItems[] = NavigationItem::make($channel->identifier)
                        ->label($channel->identifier) // Ajusta según tu necesidad
                        ->url('#') // Ajusta según tu necesidad
                        ->icon('heroicon-o-envelope')
                        ->badge(3)
                        ->url(fn(): string => route('filament.user.resources.message-imaps.index', [
                                'tenant' => Filament::getTenant(),
                                'channel' => $channel->id]
                        ))
                        ->group('Channels');
                }

                // Agregar los items de navegación al panel
                $panel->navigationItems(array_merge(
                    $panel->getNavigationItems(),
                    $navigationItems
                ));
            }
        });
    }
}

Thanks @warm wing

warm wing
#

No problem! Glad you got it to work