1. Go to this page and download the library: Download it-delmax/filament-treeview library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
it-delmax / filament-treeview example snippets
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->boolean('is_active')->default(true);
// Required for tree structure
$table->foreignId('parent_id')->nullable()->constrained('categories');
$table->integer('order')->default(0);
$table->timestamps();
});
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Openplain\FilamentTreeView\Concerns\HasTreeStructure;
class Category extends Model
{
use HasTreeStructure;
protected $fillable = ['name', 'is_active', 'parent_id', 'order'];
}
namespace App\Filament\Resources;
use App\Filament\Resources\CategoryResource\Pages;
use App\Models\Category;
use Filament\Resources\Resource;
use Filament\Schemas\Schema;
use Openplain\FilamentTreeView\Fields\IconField;
use Openplain\FilamentTreeView\Fields\TextField;
use Openplain\FilamentTreeView\Tree;
class CategoryResource extends Resource
{
protected static ?string $model = Category::class;
public static function form(Schema $schema): Schema
{
// Your form configuration
}
public static function tree(Tree $tree): Tree
{
return $tree
->fields([
TextField::make('name'),
IconField::make('is_active'),
]);
}
public static function getPages(): array
{
return [
'index' => Pages\TreeCategories::route('/'),
'create' => Pages\CreateCategory::route('/create'),
'edit' => Pages\EditCategory::route('/{record}/edit'),
];
}
}
namespace App\Filament\Resources\CategoryResource\Pages;
use App\Filament\Resources\CategoryResource;
use Openplain\FilamentTreeView\Resources\Pages\TreePage;
class TreeCategories extends TreePage
{
protected static string $resource = CategoryResource::class;
}
public static function tree(Tree $tree): Tree
{
return $tree
->maxDepth(5) // Limit nesting to 5 levels
->collapsed() // Start with nodes collapsed
->autoSave(); // Save immediately on reorder
}
// Default - fully featured tree (collapsible, expanded, manual save)
return $tree->fields([...]);
// Simple/small tree - disable collapse
return $tree
->fields([...])
->collapsible(false);
// Large tree - start collapsed for better performance
return $tree
->fields([...])
->collapsed();
// Auto-save for simple admin trees
return $tree
->fields([...])
->autoSave();
use Openplain\FilamentTreeView\Fields\TextField;
use Openplain\FilamentTreeView\Fields\IconField;
use Filament\Support\Enums\Alignment;
use Filament\Support\Enums\FontWeight;
public static function tree(Tree $tree): Tree
{
return $tree
->fields([
TextField::make('name')
->weight(FontWeight::Medium)
->dimWhenInactive(),
TextField::make('description')
->color('gray')
->limit(50)
->dimWhenInactive(),
IconField::make('is_active')
->alignEnd(),
]);
}
TextField::make('name')
// Typography
->size('sm' | 'base' | 'lg')
->weight(FontWeight::Thin | FontWeight::Medium | FontWeight::Bold)
// Colors (Filament color names)
->color('primary' | 'gray' | 'success' | 'warning' | 'danger')
// Alignment
->alignStart() // default
->alignCenter()
->alignEnd()
// Content formatting
->limit(50) // Truncate with ellipsis
->formatStateUsing(fn (string $state): string => strtoupper($state))
// Conditional dimming
->dimWhenInactive() // Defaults to 'is_active' field
->dimWhenInactive('custom_status') // Or specify a custom field
->dimWhen('field_name', value: false); // Or check any field for any value
use Filament\Actions\EditAction;
use Filament\Actions\DeleteAction;
use Filament\Actions\Action;
public static function tree(Tree $tree): Tree
{
return $tree
->recordActions([
// Navigate to edit page
EditAction::make()
->url(fn (Category $record): string =>
static::getUrl('edit', ['record' => $record])
),
// Edit in modal
Action::make('editModal')
->label('Quick Edit')
->icon('heroicon-o-pencil-square')
->fillForm(fn (Category $record): array => [
'name' => $record->name,
'description' => $record->description,
])
->form([
TextInput::make('name')-> be deleted.";
}),
]);
}
class Category extends Model
{
use HasTreeStructure;
/**
* Parent ID column name (default: 'parent_id')
*
* Override this for legacy databases with custom column names.
* Common examples: 'parent_category_id', 'category_parent_id', 'parent'
*/
public function getParentKeyName(): string
{
return 'parent_category_id'; // Your legacy column name
}
/**
* Primary key column name (default: 'id')
*/
public function getLocalKeyName(): string
{
return $this->getKeyName(); // Usually 'id'
}
/**
* Virtual depth attribute (default: 'depth')
* Calculated during queries, not stored
*/
public function getDepthName(): string
{
return 'depth';
}
/**
* Virtual path attribute (default: 'path')
* Example: [1, 5, 12] = root(1) > parent(5) > current(12)
* Calculated during queries, not stored
*/
public function getPathName(): string
{
return 'path';
}
/**
* Children relationship name (default: 'children')
*/
public function getChildrenKeyName(): string
{
return 'children';
}
/**
* Root parent value (default: null)
* Override this for existing databases that use -1, 0, or other values
* to represent root nodes (nodes without a parent)
*/
public function getParentKeyDefaultValue(): mixed
{
return null; // or -1, 0, etc.
}
}
class Category extends Model
{
use HasTreeStructure;
/**
* Your database uses 'parent_category_id' instead of 'parent_id'
*/
public function getParentKeyName(): string
{
return 'parent_category_id';
}
}
class Category extends Model
{
use HasTreeStructure;
/**
* Existing database uses -1 for root nodes
*/
public function getParentKeyDefaultValue(): mixed
{
return -1;
}
}
class Category extends Model
{
use HasTreeStructure;
public function getParentKeyName(): string
{
return 'parent_category_id'; // Custom field name
}
public function getParentKeyDefaultValue(): mixed
{
return -1; // Custom root value
}
}
public static function tree(Tree $tree): Tree
{
return $tree
->emptyStateHeading('No categories yet')
->emptyStateDescription('Get started by creating your first category.')
->emptyStateIcon('heroicon-o-rectangle-stack')
->emptyStateActions([
CreateAction::make()
->label('Create first category'),
]);
}
return $tree; // Manual save mode - safe default
return $tree->autoSave(); // Saves instantly
public static function tree(Tree $tree): Tree
{
return $tree
->modifyQueryUsing(fn (Builder $query) => $query
->where('status', 'active')
->orderBy('name')
);
}
class MenuItem extends Model
{
use HasTreeStructure;
protected $fillable = ['label', 'url', 'icon', 'parent_id', 'order', 'is_active'];
}
public static function tree(Tree $tree): Tree
{
return $tree
->maxDepth(3) // Limit menu depth
->fields([
TextField::make('label')->weight(FontWeight::Medium),
TextField::make('url')->color('gray'),
TextField::make('icon')->color('gray'),
IconField::make('is_active')->alignEnd(),
])
->recordActions([
EditAction::make(),
DeleteAction::make(),
]);
}
class Department extends Model
{
use HasTreeStructure;
public function employees()
{
return $this->hasMany(Employee::class);
}
}
public static function tree(Tree $tree): Tree
{
return $tree
->maxDepth(5)
->fields([
TextField::make('name')->weight(FontWeight::Bold),
TextField::make('manager_name')->color('gray'),
TextField::make('employees_count')
->formatStateUsing(fn (?int $state): string =>
$state ? "{$state} employees" : 'No employees'
)
->color('gray'),
]);
}