Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Filament Nestedset Laravel Package

wsmallnews/filament-nestedset

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the Package

    composer require wsmallnews/filament-nestedset:^2.0
    

    Publish config (optional):

    php artisan vendor:publish --tag="sn-filament-nestedset-config"
    
  2. Prepare Your Model

    • Add NodeTrait to your Eloquent model:
      use Kalnoy\Nestedset\NodeTrait;
      
      class YourModel extends Model
      {
          use NodeTrait;
      }
      
    • Run migration to add nested set columns:
      php artisan migrate
      
  3. Generate a NestedSet Page

    php artisan make:filament-nestedset-page
    
    • Configure the page class (e.g., Test):
      protected static string $recordTitleAttribute = 'name'; // Replace with your model's title field
      protected static string $model = YourModel::class;
      
  4. Define Form Schema Override schema(), createSchema(), or editSchema() in your page class:

    protected function schema(array $arguments): array
    {
        return [
            Forms\Components\TextInput::make('name')->required(),
        ];
    }
    
  5. Register the Page Add it to your Filament admin panel in AppServiceProvider:

    Filament::registerPages([
        \App\Filament\Pages\Test::class,
    ]);
    

Implementation Patterns

Core Workflows

  1. Tree Visualization

    • The package renders a collapsible tree UI with drag-and-drop reordering (via kalnoy/nestedset).
    • Use $recordTitleAttribute to control the displayed label for nodes.
    • Customize node labels dynamically with getRecordLabel():
      public function getRecordLabel(Model $item): string
      {
          return $item->custom_title ?? $item->name;
      }
      
  2. Parent-Child Relationships

    • Create Modal: Enable parent selection in the create modal:
      protected static bool $create_action_modal_show_parent_select = true;
      
    • Inline Action: Show "Create Child" button in rows:
      protected static bool $show_create_child_node_action_in_row = true;
      
    • The ParentSelect field uses codewithdennis/filament-select-tree.
  3. Data Organization

    • Tabs: Group nodes by a field (e.g., type):
      protected static ?string $tabFieldName = 'type';
      public function getTabs(): array
      {
          return [
              'web' => Tab::make()->label('Website'),
              'shop' => Tab::make()->label('Shop'),
          ];
      }
      
      Ensure your model’s getScopeAttributes() includes the tab field:
      public function getScopeAttributes(): array
      {
          return ['type'];
      }
      
  4. Multi-Tenancy

    • Scope nodes to the current tenant by default. Disable with:
      protected static bool $isScopedToTenant = false;
      
    • Add tenant ID to getScopeAttributes() in your model:
      public function getScopeAttributes(): array
      {
          return ['team_id'];
      }
      
  5. Level Limits

    • Restrict nesting depth:
      protected static ?int $level = 3; // Max 3 levels deep
      
    • Or dynamically:
      public function getLevel(): ?int
      {
          return auth()->user()->can('deep_nesting') ? 5 : 3;
      }
      
  6. Additional Scoping

    • Filter nodes further with nestedScoped():
      public function nestedScoped()
      {
          return ['category_id' => request('category')];
      }
      
    • Add the field to getScopeAttributes() in your model.
  7. Info List Customization

    • Add columns to the row view:
      protected function infolistSchema(): array
      {
          return [
              TextEntry::make('created_at')->dateTime(),
              Badge::make('status')->color(fn ($record) => $record->status === 'active' ? 'success' : 'danger'),
          ];
      }
      
    • Control visibility by breakpoint:
      protected static string $infolistHiddenEndpoint = 'lg'; // Hidden on lg and below
      
    • Align content:
      protected static Alignment $infolistAlignment = Alignment::Left;
      

Integration Tips

  1. Styling

    • Disable auto-loading of CSS if using a custom Filament theme:
      'autoload_assets' => false,
      
    • Override views by publishing them:
      php artisan vendor:publish --tag="sn-filament-nestedset-views"
      
  2. AI Guidelines (Laravel Boost)

    • Update Boost resources to include package guidelines:
      php artisan boost:update --discover
      
    • This generates boost.json and CLAUDE.md with usage context.
  3. Event Handling

    • Listen for node clicks via Livewire events:
      // In your Filament page's JS
      document.addEventListener('sn-filament-nestedset-leaf-click', (e) => {
          console.log('Clicked node:', e.detail.node);
      });
      
    • Trigger custom actions on node selection.
  4. Performance

    • For large trees, lazy-load children or use pagination:
      public function getEloquentQuery($query)
      {
          return $query->with(['children' => function ($q) {
              $q->limit(50); // Load first 50 children
          }]);
      }
      
  5. Testing

    • Test tree interactions with:
      $this->filament()->actingAs($user)
          ->withinPage(NestedsetPage::class)
          ->assertSeeInTree('Parent Node')
          ->click('Create Child')
          ->assertSee('Child Node');
      

Gotchas and Tips

Pitfalls

  1. Migration Conflicts

    • If adding nestedSet() to an existing table, ensure no data conflicts with the new columns (lft, rgt, depth).
    • Fix: Backup data before migrating or use a fresh table.
  2. Parent-Child Circular References

    • Avoid creating loops (e.g., Node A → Node B → Node A). The package doesn’t enforce this but may cause UI glitches.
    • Fix: Add validation in createSchema():
      Forms\Components\Select::make('parent_id')
          ->rules(['nullable', function ($attribute, $value, $fail) {
              if ($value && $this->record->isDescendantOf($value)) {
                  $fail('Cannot create a child of a descendant.');
              }
          }])
      
  3. Tab Scoping Overrides

    • If using tabs with multi-tenancy, ensure getScopeAttributes() includes both the tab field and tenant field:
      public function getScopeAttributes(): array
      {
          return ['type', 'team_id']; // Both fields must be scoped
      }
      
  4. Level Limits and Depth

    • Setting static::$level to 3 allows depths up to 3, not exactly 3. Depth 0 is root.
    • Tip: Use getLevel() for dynamic limits (e.g., based on user roles).
  5. Asset Loading Conflicts

    • If autoload_assets is true but your Filament theme overrides styles, the tree may render incorrectly.
    • Fix: Set 'autoload_assets' => false and manually include the CSS in your layout:
      <link href="{{ asset('vendor/filament-nestedset/css/nestedset.css') }}" rel="stylesheet">
      
  6. Empty State Customization

    • The empty state uses $emptyLabel and $emptyTipLabel, but these are not translated by default.
    • Fix: Publish translations:
      php artisan vendor:publish --tag="sn-filament-nestedset-translations"
      
      Then add translations to resources/lang/{locale}/filament-nestedset.php.
  7. Livewire Event Scope

    • Events like sn-filament-nestedset-leaf-click are scoped to the Livewire component. Ensure your JS listener is attached to the correct element:
      document.querySelector('[wire\\:id^="test-page"]').addEventListener('sn-filament-nestedset-leaf-click', ...);
      
  8. Multi-Tenancy Without Tenant Column

    • If your model lacks a team_id column but Filament uses multi-tenancy, the package will throw an error.
    • Fix: Either:
      • Add the column and migrate, or
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky