PHP code example of solution-forest / filament-tree

1. Go to this page and download the library: Download solution-forest/filament-tree 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/ */

    

solution-forest / filament-tree example snippets


Schema::create('categories', function (Blueprint $table) {
    $table->id();
    $table->treeColumns(); // Adds parent_id, order, title columns
    $table->timestamps();
});

// Or manually:
Schema::create('categories', function (Blueprint $table) {
    $table->id();
    $table->integer('parent_id')->default(-1)->index(); // Must default to -1!
    $table->integer('order')->default(0);
    $table->string('title');
    $table->timestamps();
});



namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use SolutionForest\FilamentTree\Concern\ModelTree;

class Category extends Model
{
    use ModelTree;

    protected $fillable = ['parent_id', 'title', 'order'];

    protected $casts = [
        'parent_id' => 'integer'
    ];
}



namespace App\Filament\Widgets;

use App\Models\Category;
use Filament\Forms\Components\TextInput;
use SolutionForest\FilamentTree\Widgets\Tree as BaseWidget;

class CategoryWidget extends BaseWidget
{
    protected static string $model = Category::class;
    protected static int $maxDepth = 3;
    protected ?string $treeTitle = 'Categories';
    protected bool $enableTreeTitle = true;

    protected function getFormSchema(): array
    {
        return [
            TextInput::make('title')->

// In your resource's ListRecords page
protected function getHeaderWidgets(): array
{
    return [CategoryWidget::class];
}

// In your PanelProvider
public function panel(Panel $panel): Panel
{
    return $panel
        ->pages([
            CategoryTree::class,
        ]);
}

// In your CategoryResource
public static function getPages(): array
{
    return [
        'index' => Pages\ListCategories::route('/'),
        'create' => Pages\CreateCategory::route('/create'),
        'edit' => Pages\EditCategory::route('/{record}/edit'),
        'tree' => Pages\CategoryTree::route('/tree'), // Add this line
    ];
}

public function getTreeRecordTitle(?\Illuminate\Database\Eloquent\Model $record = null): string
{
    if (!$record) return '';

    return "[{$record->id}] {$record->title}";
}

public function getTreeRecordIcon(?\Illuminate\Database\Eloquent\Model $record = null): ?string
{
    if ($record->parent_id != -1) {
        return null; // No icon for child records
    }

    return match ($record->title) {
        'Categories' => 'heroicon-o-tag',
        'Products' => 'heroicon-o-shopping-bag',
        'Settings' => 'heroicon-o-cog',
        default => 'heroicon-o-folder',
    };
}

protected function hasDeleteAction(): bool { return true; }
protected function hasEditAction(): bool { return true; }
protected function hasViewAction(): bool { return false; }

protected function configureEditAction(EditAction $action): EditAction
{
    return $action
        ->slideOver()
        ->modalHeading('Edit Category')
        ->modalSubmitActionLabel('Save Changes');
}

protected function configureDeleteAction(DeleteAction $action): DeleteAction
{
    return $action
        ->

protected function getTreeToolbarActions(): array
{
    return [
        \SolutionForest\FilamentTree\Actions\CreateAction::make()
            ->label('Add Category')
            ->icon('heroicon-o-plus'),
        \Filament\Actions\ExportAction::make()
            ->label('Export Tree'),
        \Filament\Actions\ImportAction::make()
            ->label('Import Categories'),
    ];
}

protected static int $maxDepth = 4; // Limit nesting depth

public function getNodeCollapsedState(?\Illuminate\Database\Eloquent\Model $record = null): bool
{
    return true; // Start with all nodes collapsed
}

// Used for all operations (fallback)
protected function getFormSchema(): array
{
    return [
        TextInput::make('title')->a(): array { /* ... */ }
protected function getEditFormSchema(): array { /* ... */ }
protected function getViewFormSchema(): array { /* ... */ }

use SolutionForest\FilamentTree\Concern\ModelTree;
use Spatie\Translatable\HasTranslations;

class Category extends Model
{
    use HasTranslations, ModelTree;

    protected $translatable = ['title'];
}

use LaraZeus\SpatieTranslatable\Actions\LocaleSwitcher;
use SolutionForest\FilamentTree\Concern\TreeRecords\Translatable;

class CategoryTree extends TreePage
{
    use Translatable;

    public function getTranslatableLocales(): array
    {
        return ['en', 'fr', 'es'];
    }

    protected function getActions(): array
    {
        return [LocaleSwitcher::make()];
    }
}

use App\Models\Menuitem;
use Illuminate\Database\Eloquent\Builder;
class MenuItemsWidget extends Tree
{
    // Accessing the current record in the widget
    public ?Model $record = null;

    protected function getTreeQuery(): Builder
    {
        return MenuItem::query()
            ->where('menu_id', $this->record?->id); // Filter by the current menu ID
    }

class Category extends Model
{
    use ModelTree;

    public function determineOrderColumnName(): string
    {
        return 'sort_order'; // Instead of 'order'
    }

    public function determineParentColumnName(): string
    {
        return 'parent_category_id'; // Instead of 'parent_id'
    }

    public function determineTitleColumnName(): string
    {
        return 'name'; // Instead of 'title'
    }

    public static function defaultParentKey(): int
    {
        return 0; // Instead of -1
    }
}

// Pre-collapse deep nodes to improve initial load
public function getNodeCollapsedState(?\Illuminate\Database\Eloquent\Model $record = null): bool
{
    return $record && $record->getDepth() > 2;
}

// Custom tree depth per implementation
protected static int $maxDepth = 5;

public function getTreeRecordTitle(?\Illuminate\Database\Eloquent\Model $record = null): string
{
    if (!$record) return '';

    $title = $record->title;

    // Add indicators
    if ($record->children()->count() > 0) {
        $title .= " ({$record->children()->count()})";
    }

    if (!$record->is_active) {
        $title = "🚫 " . $title;
    }

    return $title;
}



return [
    /**
     * Default column names for tree structure
     */
    'column_name' => [
        'order' => 'order',
        'parent' => 'parent_id',
        'title' => 'title',
    ],

    /**
     * Default parent ID for root nodes
     */
    'default_parent_id' => -1,

    /**
     * Default children relationship key
     */
    'default_children_key_name' => 'children',
];
bash
   php artisan filament:assets
   
bash
   php artisan vendor:publish --tag="filament-tree-config"
   
bash
php artisan make:filament-tree-widget CategoryWidget --model=Category
bash
php artisan make:filament-tree-page CategoryTree --model=Category
bash
php artisan make:filament-tree-page CategoryTree --resource=Category
bash
# Publish views for customization
php artisan vendor:publish --tag="filament-tree-views"

# Publish translations
php artisan vendor:publish --tag="filament-tree-translations"