TR
Başlangıç
63 · Formlar

Combobox

Uzun listeler için aranabilir seçim kutusu: tek ya da çoklu seçim, silinebilir çipler, açıklamalı ve gruplu seçenekler, Livewire metodundan ya da bir JSON adresinden arama ve listede olmayan değeri ekleme. Arama büyük/küçük harfe ve Türkçe harflere duyarsızdır; klavye ve ekran okuyucularla tam kullanılır.

PRO acun:combobox
Bileşen PRO JS girişini (@acunsoft/acun-ui-pro) ister: CSS, JavaScript ve derleme kılavuzundaki import satırı onu kendiliğinden kaydeder. Alpine'i kendiniz başlatıyorsanız registerCombobox(Alpine) çağırın.
01

Tek seçim

Seçenekleri options ile değer => metin dizisi (ya da pluck() ile bir koleksiyon) olarak verin; başlangıçta seçili olanı value belirler. Kutuya tıklayıp yazmaya başlayın: arama büyük/küçük harfe ve Türkçe harflere duyarsızdır ("sisli" yazınca "Şişli Şubesi", "igdir" yazınca "Iğdır Şubesi" bulunur) ve eşleşen kısım vurgulanır. Aşağı/yukarı ok, Home/End, Enter ve Escape listeyi klavyeyle kullandırır; Enter formu göndermez.

CANLI ÖRNEK
<acun:combobox name="sube_id" label="Şube" value="2" :options="[
    1 => 'Kadıköy Şubesi', 2 => 'Beşiktaş Şubesi', 3 => 'Üsküdar Şubesi',
    4 => 'Çankaya Şubesi', 5 => 'Karşıyaka Şubesi', 6 => 'Nilüfer Şubesi', 7 => 'Ataşehir Şubesi',
    8 => 'Şişli Şubesi', 9 => 'Çamlıca Şubesi', 10 => 'Iğdır Şubesi',
]" />
PropDeğerler
optionsdeğer => metin ya da seçenek dizileri
valueSeçili değer (metin olarak karşılaştırılır)
02

Çoklu seçim

multiple ile seçimler kutunun içinde silinebilir çipler olarak görünür; sığmazsa kutu satır satır uzar. Liste seçimden sonra açık kalır, böylece art arda seçebilirsiniz; seçili bir seçeneğe yeniden tıklamak onu kaldırır. Boş kutuda Backspace son seçimi siler. max-chips gösterilen çip sayısını sınırlar, kalanlar "+2" gibi sayılır (üzerine gelince adları görünür).

CANLI ÖRNEK
<acun:combobox name="subeler" label="Şubeler" multiple clearable :max-chips="3" :value="[1, 3, 4, 8, 9]" :options="[
    1 => 'Kadıköy Şubesi', 2 => 'Beşiktaş Şubesi', 3 => 'Üsküdar Şubesi',
    4 => 'Çankaya Şubesi', 5 => 'Karşıyaka Şubesi', 6 => 'Nilüfer Şubesi', 7 => 'Ataşehir Şubesi',
    8 => 'Şişli Şubesi', 9 => 'Çamlıca Şubesi', 10 => 'Iğdır Şubesi',
]" />
PropDeğerler
multipleÇoklu seçim; değer bir dizi
max-chipsGörünen çip sayısı
clearableTümünü temizleyen ×
03

Zengin seçenekler ve gruplar

Seçenekler dizi olarak da verilebilir: value ve label dışında description (ikinci satır; aramaya da girer), avatar (yuvarlak resim adresi), icon (Heroicons adı), disabled ve group. Aynı group değerini taşıyan seçenekler, liste kayarken üstte kalan bir başlık altında toplanır. Pasif seçenekler görünür ama seçilemez; klavye onları atlar. İç içe diziler (['Yöneticiler' => [1 => 'Ayşe', …]]) grup, Durum::cases() gibi enum listeleri seçenek olur (varsa label() metodu metni verir); id ve name alanlı diziler ve modeller de okunur.

CANLI ÖRNEK
<acun:combobox name="sorumlu" label="Sorumlu" placeholder="Personel seçin" :options="[
    ['value' => 1, 'label' => 'Ayşe Yılmaz', 'description' => '[email protected]', 'icon' => 'shield-check', 'group' => 'Yöneticiler'],
    ['value' => 2, 'label' => 'Mehmet Kaya', 'description' => '[email protected]', 'icon' => 'shield-check', 'group' => 'Yöneticiler'],
    ['value' => 3, 'label' => 'Zeynep Arslan', 'description' => 'İzinde', 'icon' => 'briefcase', 'group' => 'Satış ekibi', 'disabled' => true],
    ['value' => 4, 'label' => 'Emre Demir', 'description' => '[email protected]', 'icon' => 'briefcase', 'group' => 'Satış ekibi'],
    ['value' => 5, 'label' => 'Şule Öztürk', 'description' => '[email protected]', 'icon' => 'briefcase', 'group' => 'Satış ekibi'],
    ['value' => 6, 'label' => 'Gökhan Çelik', 'description' => 'Muhasebe', 'icon' => 'calculator', 'group' => 'Merkez ofis'],
    ['value' => 7, 'label' => 'İsmail Işık', 'description' => 'Teknik destek', 'icon' => 'wrench-screwdriver', 'group' => 'Merkez ofis'],
]" />
PropDeğerler
descriptionİkinci satır, aranır
avatarResim adresi
iconHeroicons adı
disabledSeçilemez
groupBaşlık altında toplar
04

Livewire metodundan arama

search, combobox'ı içeren Livewire bileşenindeki bir metodun adıdır. Kutuya yazıldıkça (varsayılan 300 ms beklemeyle, debounce ile değişir) metot yazılan metinle çağrılır ve döndürdüğü seçenekler listelenir; beklerken kutuda dönen bir gösterge, liste boşsa "Yükleniyor…" görünür. Liste her açılışta boş metinle de sorulur (min-chars verilmediyse). Sonuçlar değişse de seçili değerlerin adı kaybolmaz; sayfa ilk açıldığında seçili değerin adını selected-options verir. Bu sayfadaki önizleme sunucu yerine tarayıcıdaki sahte bir aramayı kullanır.

CANLI ÖRNEK
<acun:combobox
    wire:model="sorumluId"
    label="Sorumlu"
    search="personelAra"
    :selected-options="Personel::whereKey($sorumluId)->pluck('ad', 'id')"
    placeholder="Personel arayın"
    clearable
/>
PropDeğerler
searchLivewire metodunun adı
selected-optionsSeçili değerlerin etiketleri
debounce300 (ms)
min-chars0
05

Arama metodu

Metot tek parametre alır: kutuya yazılan metin (string $query; boş olabilir). Dönüş değeri seçenek listesidir: [['value' => 1, 'label' => 'Ayşe Yılmaz', 'description' => …], …], değer => metin dizisi ya da ComboboxOptions::from(…) (ikon adlarını çizilebilir yola çevirir). #[Json] metodu bileşeni yeniden çizmeden çalıştırır ve sonucu doğrudan döndürür (#[Renderless] de olur). Seçim yapıldığında kutu aynı anda yeni arama göndermez; wire:model.live değişikliği kendi isteğiyle gider ve sayfa yeniden çizilir, liste de kullanıcı yazınca ya da yeniden açınca sorulur. Sıra önemliyse liste döndürün: sayı anahtarlı bir dizi (pluck()) JSON'da nesneye dönüşür ve tarayıcı anahtarları sıraya dizer. Aramayı Acun UI arama altyapısıyla yaparsanız (SearchManager sürücüsü, searchColumn() ile eklenen arama kolonları; bkz. Arama kılavuzu) sunucu da "ayse" ile "Ayşe"yi bulur.

PHP
use Acun\Ui\Search\SearchField;
use Acun\Ui\Search\SearchManager;
use Acun\Ui\Search\SearchMode;
use Acun\Ui\Support\ComboboxOptions;
use Livewire\Attributes\Json;
use Livewire\Component;

class TalepFormu extends Component
{
    public ?int $sorumluId = null;

    // <acun:combobox search="personelAra" />: yazılan metni alır, seçenekleri döndürür.
    #[Json]
    public function personelAra(string $query): array
    {
        // ad_search ve eposta_search: migration'da $table->searchColumn('ad'), searchColumn('eposta').
        $personel = app(SearchManager::class)->driver()
            ->apply(Personel::query(), $query, [SearchField::make('ad', SearchMode::Contains), SearchField::make('eposta')])
            ->orderBy('ad')
            ->limit(20)
            ->get();

        return ComboboxOptions::from($personel->map(fn (Personel $kisi) => [
            'value' => $kisi->id,
            'label' => $kisi->ad,
            'description' => $kisi->eposta,
            'group' => $kisi->birim,
        ]));
    }
}
06

JSON adresinden arama

Livewire kullanmayan sayfalarda url bir JSON adresidir; yazılan metin ?q= ile eklenir (adresteki diğer parametreler korunur). Yanıt bir seçenek listesi, { "data": [...] } (API kaynakları, sayfalayıcılar) ya da değer => metin nesnesi olabilir; { id, name } biçimindeki kayıtlar da okunur. min-chars en az kaç karakterden sonra aranacağını belirler; geç gelen eski bir yanıt yeni sonuçların üzerine yazılmaz. Önizleme, adresi tarayıcıda yanıtlar.

CANLI ÖRNEK
<acun:combobox name="il_id" label="İl" url="/api/iller" :min-chars="2" placeholder="İl arayın" clearable />
PropDeğerler
urlJSON adresi (?q= eklenir)
min-charsAramadan önce en az karakter
07

Uç nokta

Adres, yazılan metni q parametresinde alır ve seçenekleri döndürür. Oturum çerezi gönderilir (same-origin), yani auth ara katmanı olan rotalar da çalışır.

PHP
use Illuminate\Http\Request;

Route::get('/api/iller', function (Request $request) {
    return Il::query()
        ->where('ad', 'like', '%'.$request->query('q').'%')
        ->orderBy('ad')
        ->limit(20)
        ->get()
        ->map(fn (Il $il) => ['value' => $il->id, 'label' => $il->ad]);
})->middleware('auth');
08

Yeni değer ekleme

creatable ile listede tam karşılığı olmayan metin için listenin sonunda "“…” ekle" satırı çıkar; büyük/küçük harf ve Türkçe harf farkı yeni sayılmaz ("oncelikli" yazınca "Öncelikli" eklenmez, bulunur). Enter ya da tıklama metni değer olarak seçer (değer = metin) ve kök öğeden combobox-created olayını yayınlar: detail içinde name ve value vardır.

CANLI ÖRNEK
<acun:combobox name="etiketler" label="Etiketler" multiple creatable :value="['acil']" :options="[
    'acil' => 'Acil', 'oncelikli' => 'Öncelikli', 'toptan' => 'Toptan', 'kurumsal' => 'Kurumsal müşteri',
]" />
PropDeğerler
creatableListede olmayan metni ekler
combobox-createdOlay; detail: { name, value }
09

Eklenen değeri kaydetmek

Livewire bileşeni olayı #[On] ile dinler; parametreler olayın detail alanlarıdır. Kaydettikten sonra özelliği yeni kaydın kimliğine çevirip seçenek listesini güncellerseniz combobox ikisini de yeni çizimle alır.

PHP
use Livewire\Attributes\On;

#[On('combobox-created')]
public function etiketEklendi(string $name, string $value): void
{
    if ($name === 'etiketler') {
        Etiket::firstOrCreate(['ad' => $value]);
    }
}
10

Temizleme ve sınır

clearable kutunun sağına seçimi temizleyen × ekler; tek seçimde boş kutuda Backspace de temizler. max çoklu seçimde en fazla kaç değer seçilebileceğini belirler: sınıra gelince listenin üstünde bir uyarı çıkar, diğer seçenekler pasifleşir, seçili olanlar yine kaldırılabilir. :searchable="false" yazmayı kapatır; kısa listelerde telefonda klavye açılmaz. close-on-select listenin seçimden sonra kapanıp kapanmayacağını belirler (varsayılan: tek seçimde kapanır, çoklu seçimde açık kalır).

CANLI ÖRNEK
<div class="grid gap-4 sm:grid-cols-2">
    <acun:combobox name="oncelik" label="Öncelik" value="2" clearable :searchable="false" :options="[1 => 'Düşük', 2 => 'Normal', 3 => 'Yüksek', 4 => 'Acil']" />
    <acun:combobox name="kategoriler" label="Kategoriler (en fazla 3)" multiple :max="3" :value="['elektronik', 'kitap']" :options="[
        'elektronik' => 'Elektronik', 'giyim' => 'Giyim', 'kitap' => 'Kitap', 'ev' => 'Ev ve yaşam', 'spor' => 'Spor',
    ]" />
</div>
PropDeğerler
clearable× ile temizler
maxEn fazla seçim (multiple)
searchabletrue | false
close-on-selecttek: true · çoklu: false
11

Klasik form

wire:model olmadan name verildiğinde değer gizli alanlarla gönderilir: tek seçimde name, çoklu seçimde her değer için name[] (sunucuda $request->input('etiketler', [])). required tarayıcı doğrulamasını da çalıştırır: seçim yapılmadan form gönderilmez. Önizlemede gönderilecek değerler formun altında görünür.

CANLI ÖRNEK
<form action="/siparisler" method="POST" class="space-y-4">
    @csrf
    <acun:combobox name="sube_id" label="Şube" required :options="[1 => 'Kadıköy Şubesi', 2 => 'Beşiktaş Şubesi', 3 => 'Çankaya Şubesi']" />
    <acun:combobox name="etiketler" label="Etiketler" multiple :options="['acil' => 'Acil', 'oncelikli' => 'Öncelikli', 'toptan' => 'Toptan']" />
    <acun:button type="submit">Kaydet</acun:button>
</form>
PropDeğerler
nameGizli alan adı (çoklu: name[])
requiredSeçim zorunlu
12

Doğrulama hatası ve pasif

Alan adı (name ya da wire:model) için bir doğrulama hatası varsa, acun:input gibi kutu kırmızı çerçeve alır ve mesaj altında gösterilir; çoklu seçimde etiketler.* hataları da gösterilir. Hata yokken hint yardım metni görünür. disabled kutuyu kilitler; klasik formda değer gönderilmez.

CANLI ÖRNEK
<div class="grid gap-4 sm:grid-cols-2">
    <acun:combobox name="sube" label="Şube" required :options="[1 => 'Kadıköy Şubesi', 2 => 'Beşiktaş Şubesi']" />
    <acun:combobox name="kapali_sube" label="Şube (kilitli)" value="2" disabled hint="Sipariş hazırlanmaya başlayınca değiştirilemez." :options="[1 => 'Kadıköy Şubesi', 2 => 'Beşiktaş Şubesi']" />
</div>
PropDeğerler
hintHata yokken gösterilir
disabledKilitler; değer gönderilmez
14

Alpine ile

Alpine sayfalarında x-model dışarıdaki bir değişkene bağlanır: tek seçimde bir değer, çoklu seçimde bir dizi. value => metin dizilerinin değerleri metindir ('3'); karşılaştırma her zaman metin olarak yapıldığından 3 sayısı da aynı seçeneği seçer. class, data-* gibi diğer nitelikler dış kapsayıcıya eklenir. Kullanıcı seçimi değiştirdiğinde kök öğe kabarcıklanan bir change olayı da yayınlar.

CANLI ÖRNEK
<div x-data="{ sube: '3', bolgeler: [] }" class="space-y-3">
    <acun:combobox x-model="sube" label="Şube" :options="[1 => 'Kadıköy Şubesi', 2 => 'Beşiktaş Şubesi', 3 => 'Üsküdar Şubesi']" />
    <acun:combobox x-model="bolgeler" label="Bölgeler" multiple :options="[1 => 'Marmara', 2 => 'Ege', 3 => 'İç Anadolu']" />
    <p class="text-sm text-gray-600 dark:text-zinc-400">sube: <span x-text="JSON.stringify(sube)"></span> · bolgeler: <span x-text="JSON.stringify(bolgeler)"></span></p>
</div>
PropDeğerler
x-modeltek: değer · çoklu: dizi
changeKullanıcı seçim yapınca (kabarcıklanır)
15

Livewire ile

wire:model, .live ve .live.blur çalışır (tek başına .blur Livewire 4'te istek göndermez); Livewire'dan gelen 3 sayısı '3' anahtarlı seçeneği seçer. Kutunun iç kısmı wire:ignore ile korunur: bileşen yeniden çizildiğinde açık liste, yazılan metin ve seçim bozulmaz. options, disabled ve doğrulama hatası ise yeni çizimle güncellenir; il seçilince ilçe listesinin değişmesi gibi bağımlı seçimler böyle çalışır.

BLADE
<acun:combobox wire:model.live="ilId" label="İl" :options="$iller->pluck('ad', 'id')" />
<acun:combobox wire:model.live.blur="ilceId" label="İlçe" :options="$ilceler->pluck('ad', 'id')" :disabled="! $ilId" />
<acun:combobox wire:model="personel" label="Personel" multiple :options="$personel->pluck('ad', 'id')" />
PropDeğerler
wire:model.live · .live.blur · .live.debounce.500ms
wire:keyDöngüde çizerken verin
API

Prop'lar ve slot'lar

Bileşenin kabul ettiği değerler.

PropVarsayılanAçıklama
labelnullÜstteki etiket
options[]değer => metin; seçenek dizileri; iç içe dizi (grup); enum; id/name alanlı kayıtlar
valuenullBaşlangıç değeri (multiple: dizi); wire:model / x-model varken onlar geçerlidir
multiplefalseÇoklu seçim; seçimler silinebilir çiplerdir
placeholderSeçinizSeçim yokken görünen metin
search-placeholderAra…Liste açıkken boş kutudaki ipucu
emptySonuç yokEşleşme yokken görünen metin
hintnullHata yokken alttaki yardım metni
clearablefalseSeçimi temizleyen × (tek seçimde Backspace de)
creatablefalseListede olmayan metni ekler; combobox-created olayı
searchabletruefalse: yazma kapalı (kısa listeler)
maxnullmultiple: en fazla seçim; sınırda uyarı gösterilir
max-chipsnullmultiple: görünen çip sayısı, gerisi "+N"
close-on-selecttek: true · çoklu: falseSeçimden sonra liste kapanır mı
searchnullLivewire metodu: fn (string $query): array (seçenek listesi)
urlnullJSON adresi; ?q= ile çağrılır
debounce300Uzaktan aramada bekleme (ms)
min-chars0Uzaktan aramadan önce en az karakter
selected-options[]Uzaktan listelerde seçili değerlerin etiketleri
limit200Yerel listede aynı anda çizilen en fazla seçenek
disabledfalseKilitler; gizli alan gönderilmez
requiredfalseEtikette *; tarayıcı doğrulaması ve aria-required
namenullKlasik form alanı (çoklu: name[]); hata anahtarı
wire:model / x-model — tek: değer · çoklu: dizi; .live ve .live.blur çalışır
Seçenek anahtarları — value, label, description, avatar, icon, disabled, group
Olay: combobox-created — detail: { name, value }; Livewire'da #[On('combobox-created')]
Olay: change — Kullanıcı seçimi değiştirince kök öğeden (kabarcıklanır)
Slot'lar: id kutunun kendisine (etiketin for değeri), aria-label (görünür etiket yoksa) kutuya ve listeye gider; class, data-* gibi diğer nitelikler dış kapsayıcıya eklenir. Klavye: ↓/↑ gezinir (pasifleri atlar), Home/End, PageUp/PageDown, Enter seçer, Escape kapatır, Tab kapatıp geçer, Backspace son seçimi siler.
Acun UI · ComboboxDetaylı kullanım ve örnekler