PHPackages                             kapital-online/filament-form-components - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. kapital-online/filament-form-components

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

kapital-online/filament-form-components
=======================================

Enhanced Filament form components with extended functionality for multiple select, disabled options, and more

v1.2.0(3w ago)04MITBladePHP ^8.0.2

Since Nov 9Pushed 2mo agoCompare

[ Source](https://github.com/Kapital-Online/filament-form-components)[ Packagist](https://packagist.org/packages/kapital-online/filament-form-components)[ RSS](/packages/kapital-online-filament-form-components/feed)WikiDiscussions main Synced today

READMEChangelog (1)Dependencies (8)Versions (9)Used By (0)

Kapital Filament Form Components
================================

[](#kapital-filament-form-components)

[🇹🇷 Türkçe](#t%C3%BCrk%C3%A7e) | [🇬🇧 English](#english)

---

Türkçe
------

[](#türkçe)

Filament form componentleri için geliştirilmiş özellikler: çoklu seçim, devre dışı seçenekler ve daha fazlası.

### Sorun

[](#sorun)

Filament v2'de `disableOptionWhen()` metodu tekli seçim (dropdown) için mükemmel çalışır, ancak **`multiple()` aktif edildiğinde çalışmaz**. Bunun nedeni:

1. Tekli seçim native HTML `` elementi kullanır ve disabled attribute doğal olarak çalışır
2. Çoklu seçim daha iyi UX için Choices.js kütüphanesi kullanır
3. Filament'in `transformOptionsForJs()` metodu Choices.js'e sadece `label` ve `value` gönderir, **`disabled` durumunu göndermez**

Bu paket bu sorunu çözer ve ek özellikler ekler.

### Çözüm

[](#çözüm)

Bu paket Filament'in Select componentini extend eder ve `transformOptionsForJs()` metodunu override ederek `disabled` özelliğini ekler. Choices.js zaten disabled seçenekleri desteklediği için ek JavaScript gerekmez.

### Kurulum

[](#kurulum)

#### 1. composer.json'a Ekleyin

[](#1-composerjsona-ekleyin)

Bu yerel bir paket olduğu için root `composer.json` dosyasına ekleyin:

```
{
    "require": {
        "kapital/filament-form-components": "@dev"
    }
}
```

#### 2. Composer'ı Güncelleyin

[](#2-composerı-güncelleyin)

```
composer update
```

Paket Laravel'in package discovery mekanizması ile otomatik olarak yüklenecektir.

### Kullanım

[](#kullanım)

#### Temel Kullanım (Drop-in Replacement)

[](#temel-kullanım-drop-in-replacement)

Filament'in Select componentini Kapital'in Select'i ile değiştirin:

```
// Önce
use Filament\Forms\Components\Select;

// Sonra
use Kapital\Filament\FormComponents\Components\Select;

// Kullanım tamamen aynı
Select::make('field_name')
    ->options([
        '1' => 'Seçenek 1',
        '2' => 'Seçenek 2',
        '3' => 'Seçenek 3',
    ])
    ->multiple()
    ->disableOptionWhen(fn ($value) => $value === '2')
```

**Artık `disableOptionWhen()` çoklu seçim ile mükemmel çalışıyor!**

### Özellikler

[](#özellikler)

#### 1. Düzeltilmiş `disableOptionWhen()` Çoklu Seçim İle

[](#1-düzeltilmiş-disableoptionwhen-çoklu-seçim-i̇le)

Ana özellik - devre dışı seçenekler artık çoklu seçimde düzgün çalışıyor:

```
Select::make('tags')
    ->relationship('tags', 'name')
    ->multiple()
    ->disableOptionWhen(fn ($value) => Tag::find($value)?->is_system ?? false)
```

Devre dışı seçenekler soluk görünür ve seçilemez.

#### 2. Maksimum Seçilebilir Öğe (`maxSelectable`)

[](#2-maksimum-seçilebilir-öğe-maxselectable)

Seçilebilecek öğe sayısını sınırlayın:

```
Select::make('categories')
    ->options([...])
    ->multiple()
    ->maxSelectable(3) // Maksimum 3 seçim yapılabilir
```

Özellikler:

- Backend validasyonu (aşılırsa form gönderilmez)
- Frontend validasyonu Choices.js ile (kullanıcı dostu geri bildirim)
- Closure desteği ile dinamik limitler

```
->maxSelectable(fn () => auth()->user()->isPremium() ? 10 : 3)
```

#### 3. Minimum Seçilebilir Öğe (`minSelectable`)

[](#3-minimum-seçilebilir-öğe-minselectable)

Minimum sayıda seçim zorunluluğu:

```
Select::make('required_tags')
    ->options([...])
    ->multiple()
    ->minSelectable(2) // En az 2 seçim gerekli
```

Özellikler:

- Backend validasyonu
- Closure desteği ile dinamik limitler

```
->minSelectable(fn () => auth()->user()->isAdmin() ? 0 : 1)
```

#### 4. Tümünü Seç Seçeneği (`selectAllOption`)

[](#4-tümünü-seç-seçeneği-selectalloption)

"Tümünü Seç" butonu ekler. Tıklandığında disabled olmayan tüm seçenekleri otomatik seçer:

```
Select::make('permissions')
    ->options([...])
    ->multiple()
    ->selectAllOption() // "Tümünü Seç" butonu ekler
    ->disableOptionWhen(fn($value) => $value === 'dangerous_permission') // Disabled olanlar seçilmez
```

Özellikler:

- Disabled seçenekleri otomatik filtreler
- Form alanının yanında hint action olarak görünür
- Closure desteği ile dinamik gösterim

```
->selectAllOption(fn () => auth()->user()->isAdmin())
```

#### 5. Tümünü Temizle Seçeneği (`deselectAllOption`)

[](#5-tümünü-temizle-seçeneği-deselectalloption)

"Tümünü Temizle" butonu ekler. Tıklandığında tüm seçimleri kaldırır:

```
Select::make('filters')
    ->options([...])
    ->multiple()
    ->deselectAllOption() // "Tümünü Temizle" butonu ekler
```

Özellikler:

- Tüm seçimleri bir tıkla temizler
- Kırmızı renkte ve X ikonu ile görünür
- Closure desteği ile dinamik gösterim

```
->deselectAllOption(fn () => auth()->user()->canClearAll())
```

#### 6. Master-Detail Table (Filament v2)

[](#6-master-detail-table-filament-v2)

Bu paket Filament v2 resource tabloları için master-detail altyapısı da içerir.

Öne çıkanlar:

- Satır bazlı aç/kapa detayı (ikonlu)
- Detail içeriğini sadece açılınca render etme (lazy)
- Mevcut Filament table zinciriyle uyumlu kullanım
- Relation/query/livewire tabanlı detail tanımına uygun fluent API

##### Gerekli Importlar

[](#gerekli-importlar)

```
use Filament\Resources\Table;
use Kapital\Filament\FormComponents\Resources\Table as MasterDetailResourceTable;
```

##### Resource Kullanımı

[](#resource-kullanımı)

```
public static function table(Table $table): Table
{
    if ($table instanceof MasterDetailResourceTable) {
        $table->masterDetailLivewire(
            component: 'overdue-payment-plan-report-transactions-table',
            parameters: fn (OverduePaymentPlanReport $record): array => [
                'userId' => $record->user_id,
            ],
            key: fn (OverduePaymentPlanReport $record): string => 'overdue-payment-plan-report-' . $record->getKey(),
        );
    }

    return $table
        ->columns([
            // Filament columns...
        ]);
}
```

##### List Page Kullanımı

[](#list-page-kullanımı)

İlgili resource list page sınıfında trait eklenmelidir:

```
use Kapital\Filament\FormComponents\Tables\Concerns\InteractsWithMasterDetailTable;

class ListOverduePaymentPlanReports extends ListRecords
{
    use InteractsWithMasterDetailTable;
}
```

##### API Özeti

[](#api-özeti)

- `masterDetailLivewire(component, parameters, key, expandable, expandIcon, collapseIcon, wrapperClass)`
- `masterDetailRelation(relation)`
- `masterDetailQuery(closure)`

Not: Filament v2 `Resource::table()` method imzası `Filament\Resources\Table` beklediği için method parametresi Filament tipiyle kalmalıdır. Paketin master-detail özellikleri runtime’da `instanceof MasterDetailResourceTable` ile etkinleştirilir.

##### Bilinen Kısıt / Öneri

[](#bilinen-kısıt--öneri)

Nested modal içinde tekrar modal açan table action akışları Alpine/Livewire tarafında sorun çıkarabilir. Bu tip senaryolarda detail içeriğini aynı sayfada inline açmak veya action akışını modal dışına taşımak daha stabil sonuç verir.

### Gerçek Dünya Örneği

[](#gerçek-dünya-örneği)

```
use Kapital\Filament\FormComponents\Components\Select;
use App\Models\Tag;

Select::make('tags')
    ->label('Sipariş Etiketleri')
    ->relationship('tags', 'name')
    ->multiple()
    ->disableOptionWhen(function ($value) {
        // Sistem etiketlerini devre dışı bırak - kaldırılamazlar
        return Tag::find($value)?->is_system ?? false;
    })
    ->selectAllOption() // "Tümünü Seç" butonu (disabled olanları atlar)
    ->deselectAllOption() // "Tümünü Temizle" butonu
    ->maxSelectable(5) // Sipariş başına maksimum 5 etiket
    ->minSelectable(1) // En az 1 etiket gerekli
    ->searchable()
    ->preload()
    ->helperText('Sistem etiketleri devre dışıdır ve değiştirilemez.')
```

### Tüm Özellikler Karşılaştırması

[](#tüm-özellikler-karşılaştırması)

ÖzellikFilament v2 SelectKapital Enhanced SelectTekli seçim + `disableOptionWhen()`✅ Çalışıyor✅ ÇalışıyorÇoklu seçim + `disableOptionWhen()`❌ Bozuk✅ Düzeltildi`maxSelectable()`❌ Yok✅ Var`minSelectable()`❌ Yok✅ Var`selectAllOption()`❌ Yok✅ Var`deselectAllOption()`❌ Yok✅ VarDiğer tüm Filament özellikleri✅✅ Tam uyumlu### Teknik Detaylar

[](#teknik-detaylar)

#### Nasıl Çalışır

[](#nasıl-çalışır)

Düzeltme oldukça basit. Paket tek bir metodu override eder:

```
protected function transformOptionsForJs(array $options): array
{
    return collect($options)
        ->map(fn ($label, $value): array => [
            'label' => $label,
            'value' => strval($value),
            'disabled' => $this->isOptionDisabled($value, $label), // Bu satır eklendi
        ])
        ->values()
        ->all();
}
```

Choices.js (Filament'in çoklu seçim için kullandığı kütüphane) `disabled` özelliğini doğal olarak destekler. Bunu options array'ine ekleyerek, devre dışı seçenekler otomatik olarak çalışır.

#### Validasyon

[](#validasyon)

Tüm validasyon güvenlik için backend'de gerçekleşir:

- `maxSelectable()` bir `max:X` validasyon kuralı ekler
- `minSelectable()` bir `min:X` validasyon kuralı ekler
- Devre dışı seçenekler sunucu tarafında validate edilir (client-side bypass edilse bile gönderilemez)

Frontend özellikleri (Choices.js maxItemCount gibi) kullanıcı dostu geri bildirim sağlar ancak güvenlik için bunlara güvenilmez.

### Uyumluluk

[](#uyumluluk)

- **Laravel**: 9.x, 10.x
- **Filament**: v2.x
- **PHP**: 8.0.2+

### Sorun Giderme

[](#sorun-giderme)

#### Devre dışı seçenekler hala seçilebiliyor

[](#devre-dışı-seçenekler-hala-seçilebiliyor)

Doğru Select componentini import ettiğinizden emin olun:

```
// Doğru
use Kapital\Filament\FormComponents\Components\Select;

// Yanlış
use Filament\Forms\Components\Select;
```

#### Composer paketi bulamıyor

[](#composer-paketi-bulamıyor)

Paketin doğru konumda olduğundan emin olun:

- Yol: `lib/filament-form-components/`
- Root `composer.json` dosyasında paket `require` bölümünde var
- `composer update` veya `composer dump-autoload` çalıştırın

#### Max/min validasyon çalışmıyor

[](#maxmin-validasyon-çalışmıyor)

Validasyon kuralları otomatik olarak eklenir. Kontrol edin:

1. `->multiple()` kullanıyorsunuz
2. Form validate ediliyor
3. Validasyon hataları için Laravel loglarını kontrol edin

---

English
-------

[](#english)

Enhanced Filament form components with extended functionality for multiple select, disabled options, and more.

### The Problem

[](#the-problem)

In Filament v2, the `disableOptionWhen()` method works perfectly for single select dropdowns, but **fails to work when `multiple()` is enabled**. This is because:

1. Single select uses native HTML `` elements where disabled attributes work natively
2. Multiple select uses Choices.js library for better UX
3. Filament's `transformOptionsForJs()` method only passes `label` and `value` to Choices.js, **omitting the `disabled` state**

This package fixes this issue and adds additional features for enhanced select components.

### The Solution

[](#the-solution)

This package extends Filament's Select component and overrides the `transformOptionsForJs()` method to include the `disabled` property. Choices.js already supports disabled options natively, so no additional JavaScript is required.

### Installation

[](#installation)

#### 1. Add to composer.json

[](#1-add-to-composerjson)

Since this is a local package, add it to your root `composer.json`:

```
{
    "require": {
        "kapital/filament-form-components": "@dev"
    }
}
```

#### 2. Update Composer

[](#2-update-composer)

```
composer update
```

The package will be auto-discovered via Laravel's package discovery mechanism.

### Usage

[](#usage)

#### Basic Usage (Drop-in Replacement)

[](#basic-usage-drop-in-replacement)

Simply replace Filament's Select component with Kapital's Select:

```
// Before
use Filament\Forms\Components\Select;

// After
use Kapital\Filament\FormComponents\Components\Select;

// Usage remains exactly the same
Select::make('field_name')
    ->options([
        '1' => 'Option 1',
        '2' => 'Option 2',
        '3' => 'Option 3',
    ])
    ->multiple()
    ->disableOptionWhen(fn ($value) => $value === '2')
```

**Now `disableOptionWhen()` works perfectly with `multiple()` enabled!**

### Features

[](#features)

#### 1. Fixed `disableOptionWhen()` with Multiple Select

[](#1-fixed-disableoptionwhen-with-multiple-select)

The primary feature - disabled options now work correctly with multiple select:

```
Select::make('tags')
    ->relationship('tags', 'name')
    ->multiple()
    ->disableOptionWhen(fn ($value) => Tag::find($value)?->is_system ?? false)
```

Disabled options will appear grayed out and cannot be selected.

#### 2. Maximum Selectable Items (`maxSelectable`)

[](#2-maximum-selectable-items-maxselectable)

Limit the number of items that can be selected:

```
Select::make('categories')
    ->options([...])
    ->multiple()
    ->maxSelectable(3) // Maximum 3 selections allowed
```

Features:

- Backend validation (prevents form submission if exceeded)
- Frontend validation via Choices.js (user-friendly feedback)
- Supports closures for dynamic limits

```
->maxSelectable(fn () => auth()->user()->isPremium() ? 10 : 3)
```

#### 3. Minimum Selectable Items (`minSelectable`)

[](#3-minimum-selectable-items-minselectable)

Require a minimum number of selections:

```
Select::make('required_tags')
    ->options([...])
    ->multiple()
    ->minSelectable(2) // At least 2 selections required
```

Features:

- Backend validation
- Supports closures for dynamic limits

```
->minSelectable(fn () => auth()->user()->isAdmin() ? 0 : 1)
```

#### 4. Select All Option (`selectAllOption`)

[](#4-select-all-option-selectalloption)

Adds a "Select All" button. When clicked, automatically selects all non-disabled options:

```
Select::make('permissions')
    ->options([...])
    ->multiple()
    ->selectAllOption() // Adds "Select All" button
    ->disableOptionWhen(fn($value) => $value === 'dangerous_permission') // Disabled ones won't be selected
```

Features:

- Automatically filters out disabled options
- Appears as a hint action next to the field
- Supports closures for dynamic visibility

```
->selectAllOption(fn () => auth()->user()->isAdmin())
```

#### 5. Deselect All Option (`deselectAllOption`)

[](#5-deselect-all-option-deselectalloption)

Adds a "Deselect All" button. When clicked, clears all selections:

```
Select::make('filters')
    ->options([...])
    ->multiple()
    ->deselectAllOption() // Adds "Clear All" button
```

Features:

- Clears all selections with one click
- Appears in red color with X icon
- Supports closures for dynamic visibility

```
->deselectAllOption(fn () => auth()->user()->canClearAll())
```

#### 6. Master-Detail Table (Filament v2)

[](#6-master-detail-table-filament-v2-1)

This package also includes a master-detail infrastructure for Filament v2 resource tables.

Highlights:

- Row-level expand/collapse detail with icon
- Lazy detail rendering (content is mounted only when expanded)
- Compatible with standard Filament table chaining
- Fluent API suitable for relation/query/livewire detail definitions

##### Required Imports

[](#required-imports)

```
use Filament\Resources\Table;
use Kapital\Filament\FormComponents\Resources\Table as MasterDetailResourceTable;
```

##### Resource Usage

[](#resource-usage)

```
public static function table(Table $table): Table
{
    if ($table instanceof MasterDetailResourceTable) {
        $table->masterDetailLivewire(
            component: 'overdue-payment-plan-report-transactions-table',
            parameters: fn (OverduePaymentPlanReport $record): array => [
                'userId' => $record->user_id,
            ],
            key: fn (OverduePaymentPlanReport $record): string => 'overdue-payment-plan-report-' . $record->getKey(),
        );
    }

    return $table
        ->columns([
            // Filament columns...
        ]);
}
```

##### List Page Usage

[](#list-page-usage)

Add the trait to your resource list page class:

```
use Kapital\Filament\FormComponents\Tables\Concerns\InteractsWithMasterDetailTable;

class ListOverduePaymentPlanReports extends ListRecords
{
    use InteractsWithMasterDetailTable;
}
```

##### API Summary

[](#api-summary)

- `masterDetailLivewire(component, parameters, key, expandable, expandIcon, collapseIcon, wrapperClass)`
- `masterDetailRelation(relation)`
- `masterDetailQuery(closure)`

Note: Filament v2 `Resource::table()` signature must keep `Filament\Resources\Table` as the method argument. Package master-detail features are enabled at runtime via `instanceof MasterDetailResourceTable`.

##### Known Limitation / Recommendation

[](#known-limitation--recommendation)

Nested table actions that open another modal inside an existing modal may cause Alpine/Livewire issues. In such cases, prefer inline detail rendering on the same page or move the action flow outside nested modals.

### Real-World Example

[](#real-world-example)

```
use Kapital\Filament\FormComponents\Components\Select;
use App\Models\Tag;

Select::make('tags')
    ->label('Order Tags')
    ->relationship('tags', 'name')
    ->multiple()
    ->disableOptionWhen(function ($value) {
        // Disable system tags - they cannot be removed
        return Tag::find($value)?->is_system ?? false;
    })
    ->selectAllOption() // "Select All" button (skips disabled ones)
    ->deselectAllOption() // "Clear All" button
    ->maxSelectable(5) // Maximum 5 tags per order
    ->minSelectable(1) // At least 1 tag required
    ->searchable()
    ->preload()
    ->helperText('System tags are disabled and cannot be changed.')
```

### All Features Comparison

[](#all-features-comparison)

FeatureFilament v2 SelectKapital Enhanced SelectSingle select with `disableOptionWhen()`✅ Works✅ WorksMultiple select with `disableOptionWhen()`❌ Broken✅ Fixed`maxSelectable()`❌ Not available✅ Available`minSelectable()`❌ Not available✅ Available`selectAllOption()`❌ Not available✅ Available`deselectAllOption()`❌ Not available✅ AvailableAll other Filament features✅✅ Fully compatible### Technical Details

[](#technical-details)

#### How It Works

[](#how-it-works)

The fix is remarkably simple. The package overrides a single method:

```
protected function transformOptionsForJs(array $options): array
{
    return collect($options)
        ->map(fn ($label, $value): array => [
            'label' => $label,
            'value' => strval($value),
            'disabled' => $this->isOptionDisabled($value, $label), // Added this line
        ])
        ->values()
        ->all();
}
```

Choices.js (the library Filament uses for multiple selects) natively supports the `disabled` property. By including it in the options array, disabled options automatically work.

#### Validation

[](#validation)

All validation happens on the backend for security:

- `maxSelectable()` adds a `max:X` validation rule
- `minSelectable()` adds a `min:X` validation rule
- Disabled options are validated server-side (cannot be submitted even if client-side is bypassed)

Frontend features (like Choices.js maxItemCount) provide user-friendly feedback but aren't relied upon for security.

### Compatibility

[](#compatibility)

- **Laravel**: 9.x, 10.x
- **Filament**: v2.x
- **PHP**: 8.0.2+

### Troubleshooting

[](#troubleshooting)

#### Disabled options still selectable

[](#disabled-options-still-selectable)

Make sure you're importing the correct Select component:

```
// Correct
use Kapital\Filament\FormComponents\Components\Select;

// Wrong
use Filament\Forms\Components\Select;
```

#### Composer can't find the package

[](#composer-cant-find-the-package)

Ensure the package is in the correct location:

- Path: `lib/filament-form-components/`
- Root `composer.json` has the package in `require` section
- Run `composer update` or `composer dump-autoload`

#### Max/min validation not working

[](#maxmin-validation-not-working)

The validation rules are automatically added. Check:

1. You're using `->multiple()`
2. The form is being validated
3. Check Laravel logs for validation errors

---

License
-------

[](#license)

MIT

Credits
-------

[](#credits)

Created by Kapital Online for internal use and open-sourced for the community.

Contributing
------------

[](#contributing)

This is an internal package, but suggestions and bug reports are welcome.

###  Health Score

38

—

LowBetter than 83% of packages

Maintenance91

Actively maintained with recent releases

Popularity3

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity46

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~36 days

Recently: every ~53 days

Total

7

Last Release

22d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/49042b60f3728ff715d179d98a04e527674d402e95f4a85a55ff8c33769bca1f?d=identicon)[tgedikli](/maintainers/tgedikli)

---

Top Contributors

[![tgedikli](https://avatars.githubusercontent.com/u/611037?v=4)](https://github.com/tgedikli "tgedikli (5 commits)")

### Embed Badge

![Health badge](/badges/kapital-online-filament-form-components/health.svg)

```
[![Health](https://phpackages.com/badges/kapital-online-filament-form-components/health.svg)](https://phpackages.com/packages/kapital-online-filament-form-components)
```

###  Alternatives

[filament/filament

A collection of full-stack components for accelerated Laravel app development.

3829.6M3.7k](/packages/filament-filament)[psalm/plugin-laravel

Psalm plugin for Laravel

3355.3M346](/packages/psalm-plugin-laravel)[promethys/revive

A 'RecycleBin' page where users can restore or delete permanently soft-deleted models.

162.9k](/packages/promethys-revive)[biostate/filament-menu-builder

An Elegant Menu Builder for FilamentPHP

6528.1k2](/packages/biostate-filament-menu-builder)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
