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 Tree View Laravel Package

openplain/filament-tree-view

Drag-and-drop tree view for Filament resources to manage hierarchical data. Built on Laravel Adjacency List and Atlassian Pragmatic Drag & Drop. Supports depth limits, auto or batch save, custom fields, actions, dark mode, accessibility, and safe moves.

View on GitHub
Deep Wiki
Context7
## Getting Started

### Minimal Setup
1. **Installation**:
   ```bash
   composer require openplain/filament-tree-view

Publish the config (if needed):

php artisan vendor:publish --provider="Openplain\FilamentTreeView\FilamentTreeViewServiceProvider"
  1. Basic Integration: Replace your Table with TreeView in a Filament resource:

    use Openplain\FilamentTreeView\Columns\TreeViewColumn;
    use Openplain\FilamentTreeView\TreeView;
    
    public static function table(Table $table): Table
    {
        return TreeView::make()
            ->columns([
                TreeViewColumn::make('name'),
                // Other columns...
            ])
            ->query($this->query());
    }
    
  2. First Use Case: Display a category hierarchy with drag-and-drop:

    TreeView::make()
        ->columns([
            TreeViewColumn::make('title'),
            Columns\TextColumn::make('description'),
        ])
        ->query(Category::query())
        ->parentColumn('parent_id') // Required
        ->orderColumn('order_column') // Optional
        ->bulkActions([...]); // Optional
    

Key Configuration

  • Required: Define parentColumn (foreign key to parent) and orderColumn (for sorting).
    • Note: Now supports non-integer primary keys (e.g., UUIDs, strings) due to string comparison fix in v0.5.6.
  • Optional: Customize depthColumn, iconColumn, or indentation for visual hierarchy.

Implementation Patterns

Core Workflows

1. Hierarchical Data Management

// Define parent-child relationships (now works with non-integer keys)
TreeView::make()
    ->parentColumn('parent_id') // Supports UUIDs, strings, etc.
    ->orderColumn('sort_order')
    ->query(Post::query());

// Customize indentation (default: 20px)
->indentation(30);

2. Drag-and-Drop Reordering

Enable with:

->enableDragAndDrop()
    ->onReorder(function (array $items) {
        // Handle reorder logic (e.g., update `order_column`)
        Post::whereIn('id', array_keys($items))
            ->update(['sort_order' => array_values($items)]);
    });

3. Bulk Actions

->bulkActions([
    Tables\Actions\DeleteBulkAction::make(),
    Tables\Actions\ForceDeleteBulkAction::make(),
]);

4. Nested Columns

TreeViewColumn::make('title')
    ->toggleable(isToggledHiddenByDefault: true)
    ->searchable();

5. Custom Actions

->actions([
    Tables\Actions\EditAction::make(),
    Tables\Actions\ViewAction::make(),
    function (Post $record) {
        return Action::make('Custom')
            ->icon('heroicon-o-pencil')
            ->url(fn () => route('posts.edit', $record));
    },
]);

6. Handling Non-Integer Primary Keys

// Example with UUIDs
TreeView::make()
    ->parentColumn('parent_uuid') // String-based parent key
    ->orderColumn('sort_order')
    ->query(Post::query());

Integration Tips

With Adjacency List

// Assuming `parent_id` (now supports non-integer) and `lft`, `rgt` columns
TreeView::make()
    ->parentColumn('parent_id')
    ->orderColumn('lft') // Use left/right for nested sets
    ->query(Post::query());

With Custom Queries

->query(fn () => Post::where('published', true)->with('author'))
    ->searchable(['title', 'content']);

Conditional Columns

->columns([
    TreeViewColumn::make('title')
        ->visible(fn ($record) => $record->is_published),
]);

Custom Styling

->headerActions([
    Header::make()->slot([
        Button::make('Refresh')
            ->icon('heroicon-o-arrow-path')
            ->action(fn () => $this->refresh()),
    ]),
]);

Livewire Modal Stability

  • Fix for v0.5.6: Actions are now preserved during Livewire modal rehydration (e.g., after drag-and-drop in a modal).
  • Example: Drag-and-drop reordering inside a modal will retain mounted actions post-update.

Gotchas and Tips

Pitfalls

  1. Performance with Large Trees

    • Issue: Deeply nested trees (>5 levels) may cause UI lag.
    • Fix: Use ->limitDepth(3) or lazy-load children via AJAX.
  2. Drag-and-Drop Conflicts

    • Issue: Conflicts with other drag-and-drop libraries (e.g., Filament’s Sortable).
    • Fix: Ensure no duplicate data-js attributes in your Blade templates.
  3. Order Column Misconfiguration

    • Issue: Missing orderColumn throws RuntimeException.
    • Fix: Always define orderColumn (even if unused for display).
  4. Circular References

    • Issue: Self-referential parent-child relationships (e.g., parent_id pointing to itself).
    • Fix: Validate in your model:
      public function setParentIdAttribute($value) {
          if ($value == $this->id) {
              throw new \Exception("Cannot be its own parent.");
          }
          $this->attributes['parent_id'] = $value;
      }
      
  5. Non-Integer Primary Key Issues (New in v0.5.6)

    • Issue: Older versions may fail with string/UUID keys.
    • Fix: Update to v0.5.6+ and ensure parentColumn uses the correct key type (e.g., parent_uuid for UUIDs).

Debugging

  1. Check Tree Structure Use Tinker to verify your hierarchy:

    php artisan tinker
    >>> Post::with('children')->find(1)->toTree();
    
  2. Log Reorder Events

    ->onReorder(function (array $items) {
        \Log::info('Reordered items:', $items);
        // Update logic...
    });
    
  3. Disable JavaScript

    • If drag-and-drop fails, test with JS disabled to isolate issues.
  4. Livewire Modal Debugging

    • If actions disappear after modal rehydration, verify:
      • No custom JavaScript is interfering with Livewire’s event handling.
      • The TreeView component is properly mounted in the modal.

Tips

  1. Use toTree() for Testing Leverage staudenmeir/eloquent-nestedset or spatie/laravel-activitylog to debug hierarchies:

    Post::find(1)->toTree();
    
  2. Custom Icons for Depth

    ->columns([
        TreeViewColumn::make('title')
            ->icon(fn ($record) => match ($record->depth) {
                0 => 'heroicon-o-home',
                1 => 'heroicon-o-folder',
                default => 'heroicon-o-document',
            }),
    ]);
    
  3. Optimize for Mobile

    ->enableCollapseAll()
    ->enableExpandAll();
    
  4. Extend with Custom Columns Create a custom column class:

    namespace App\Filament\Columns;
    
    use Openplain\FilamentTreeView\Columns\TreeViewColumn;
    
    class CustomTreeViewColumn extends TreeViewColumn {
        protected string $view = 'filament-tree-view::columns.custom';
    }
    
  5. Cache Tree Queries For read-heavy apps, cache the tree structure:

    ->query(fn () => cache()->remember('tree-data', now()->addHours(1), function () {
        return Post::query();
    }));
    
  6. Handle Soft Deletes Ensure your query respects soft deletes:

    ->query(Post::withTrashed()->query());
    
  7. Localization Override labels in your Filament config:

    'filament-tree-view' => [
        'tree' => [
            'actions' => [
                'expand_all' => 'Expand All',
                'collapse_all' => 'Collapse All',
            ],
        ],
    ],
    
  8. UUID/Non-Integer Key Workflow

    • Model Setup:
      use Illuminate\Database\Eloquent\Concerns\HasUuids;
      
      class Post extends Model {
          use HasUuids;
          // ...
      }
      
    • TreeView Usage:
      TreeView::make()
          ->parentColumn('
      
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.
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope