K

Tabulka

Sloupce

Všechny typy sloupců a základní API, které sdílejí — popisky, viditelnost, autorizace, řazení, formátování a inline editace.

Na této stránce

Wire Table poskytuje 19 typů sloupců. Všechny sdílejí stejné základní API sloupce pro popisky, viditelnost, autorizaci, řazení, formátování a inline editaci — dokumentované níže. Typ vyberte podle vykreslení buňky; sdílené API sáhněte na kterýkoli z nich.

Typy sloupců

Sloupec Použití pro
TextColumn Univerzální text s presety formátování data/měny/čísel
BadgeColumn Status pilulky s barvou a ikonou, vč. self-coloringu enumů
MoneyColumn Částky, doprava a tabulárně; metrika stacked karty
MetricColumn Měření: agregované číslo s volitelnou čárou trendu
PhoneColumn Telefonní číslo zapsané ke čtení a odkázané k vytáčení
BooleanColumn True/false jako ikona (fajfka / křížek)
IconColumn Ikony podle stavu nebo dynamicky resolvované
ImageColumn Avatary a náhledy
ButtonColumn Tlačítko s odkazem nebo Livewire akcí v buňce
ToggleColumn Inline editovatelný přepínač on/off
CheckboxColumn Inline editovatelné zaškrtávátko (hustší ToggleColumn)
SelectColumn Inline editovatelný rozbalovací seznam (možnosti, relace, enumy)
TextInputColumn Inline editovatelný text/číslo/email input
StackedColumn Layouty avatar + jméno + email na sobě
SplitColumn Poskládat několik sloupců vedle sebe
PollColumn Buňky se živě pollovaným stavem/postupem
ColorColumn Uložená CSS barva jako vzorník
RatingColumn Číselné hodnocení jako hvězdičky
TagsColumn Vícehodnotový stav jako chipsy

Koncepty

Sdílené API sloupce

Každý sloupec dědí tyto schopnosti ze základní třídy Column.

Factory a identita

Column::make(string $name) // statická factory — $name je cesta v tečkové notaci
->label(string|Closure $label) // zobrazovací popisek v <th> (automaticky generovaný z názvu)
->getName(): string // získat název sloupce
->getLabel(): string // získat resolvovaný popisek

Řazení

->sortable(bool $sortable = true, ?Closure $query = null)
->isSortable(): bool
->getSortColumn(): ?string // atribut, podle kterého hlavička řadí
 
// Vlastní logika řazení
->sortUsing(Closure $fn)

isSortable() rozhoduje, jestli je hlavička klikací; getSortColumn() rozhoduje, podle čeho ten klik řadí. U běžného sloupce jsou to tytéž řetězce — jeho vlastní jméno včetně tečkové cesty přes relaci — takže ho nikdy nevoláte. Rozejdou se u složeného sloupce: SplitColumn je zaregistrovaný pod jménem skupiny, kterou kreslí, a odpovídá prvním řaditelným dítětem, které drží. Dotazový šev se ptá sloupce místo toho, aby použil jméno z kliknutí — a to je to, co složené hlavičce brání řadit podle atributu, který neexistuje.

TextColumn::make('full_name')
->sortable()
->sortUsing(function (Builder $query, string $direction) {
$query->orderBy('last_name', $direction)
->orderBy('first_name', $direction);
})

Hledání

->searchable(bool|array $searchable = true)
->isSearchable(): bool
 
// Předejte pole pro hledání v konkrétních DB sloupcích (když je název sloupce virtuální)
->searchable(['first_name', 'last_name', 'email'])
 
// Vlastní logika hledání
->searchUsing(Closure $fn)
 
// Deklarovat, co sloupec drží, aby šlo do hledání psát >100 a 10..20
->searchAs(SearchValueType|string $type) // 'text' | 'numeric' | 'date' | 'code'
 
// Získat resolvované sloupce hledání
->getSearchColumns(): array

searchColumns(array $columns) jako samostatný setter existuje jen na StackedColumn. Na ostatních sloupcích předejte pole rovnou do searchable().

// Hledat napříč více DB sloupci
TextColumn::make('user')
->searchable(['first_name', 'last_name', 'email'])
 
// Vlastní logika hledání
TextColumn::make('full_name')
->searchable()
->searchUsing(function (Builder $query, string $search) {
$query->where(DB::raw("CONCAT(first_name, ' ', last_name)"), 'like', "%{$search}%");
})

searchAs() má smysl teprve tehdy, když tabulka zapne hledání rozsahů. Typ hodnoty se obvykle odvodí z castů modelu — cast decimal:2 nebo datetime stačí — deklarujte ho tedy jen tam, kde za sloupec casty mluvit nemohou:

// Model nemá pro `amount` žádný cast, takže se z něj nedá nic odvodit.
TextColumn::make('amount')
->searchable()
->searchAs('numeric') // ">1000" a "10..20" se teď dostanou i na tento sloupec

Sloupec ponechaný jako text porovnání přeskočí, místo aby porovnával lexikograficky — chybná nebo chybějící deklarace tak jen zúží, čemu hledání rozumí, nikdy nevrátí špatné řádky.

Samotná deklarace nic nezapíná. Hledatelný sloupec, který typ deklaruje, zatímco hledání tabulky rozsahy nečte, se při renderu tabulky odmítne a pojmenuje chybějící volání — jinak by se tabulka vrátila prázdná, protože 10..20 by se hledalo jako doslovný text.

'code' je jediný typ, který se nikdy neodvozuje: říká, že hodnota je řada plus číslo doplněné nulami (8866 01, 8866 02), což je právě to, co dělá porovnání textem správným — a ví to jen vlastník. Odemyká rozsahy uvnitř řady8866 01..08.

Viditelnost a přepínatelnost

->hidden(bool|Closure $hidden = true) // skrýt sloupec
->isHidden(): bool
 
// Přepínatelné uživatelem (výběr sloupců)
->toggleable(bool $toggleable = true)
 
// Podle oprávnění
->permission(?string $permission) // viditelné jen když má uživatel oprávnění
->visible(Closure $callback) // vlastní callback viditelnosti (jen Closure)
 
// Viditelnost buňky pro každý záznam (redakce jedné buňky na řádek)
->visibleForRecord(Closure $callback) // fn ($record) => bool

->hidden(), ->permission(), ->visible() a ->authorize() rozhodují, zda sloupec v tabulce vůbec existuje — vyhodnocují se jednou, bez záznamu (řídí také hlavičku, přepínání sloupců a export). Pro skrytí nebo redakci jedné buňky per řádek — např. zobrazit salary jen pro záznamy, které uživatel smí vidět — použijte ->visibleForRecord(fn ($record) => …), který běží při renderu buňky se záznamem řádku. Skrytá buňka se vykreslí prázdná; sloupec dál zabírá své místo v každém dalším řádku.

TextColumn::make('salary')
->visibleForRecord(fn ($record) => auth()->user()->can('viewSalary', $record));

Responzivní breakpointy

->visibleFrom(string $breakpoint) // skryté pod tímto breakpointem
->hiddenFrom(string $breakpoint) // skryté od tohoto breakpointu nahoru
->onlyOnMobile() // viditelné jen na mobilu (<md)
->onlyOnDesktop() // viditelné jen na desktopu (≥lg)
->onlyOnTabletAndUp() // viditelné od md nahoru
->onlyOnLargeScreens() // viditelné od xl nahoru
TextColumn::make('phone')
->visibleFrom('md') // skryté na mobilu, viditelné od md
 
TextColumn::make('notes')
->onlyOnLargeScreens() // viditelné jen na xl+

Responzivní varianty zobrazení

// Vlastní render pro mobil vs desktop
->mobileDisplayUsing(Closure $fn)
->desktopDisplayUsing(Closure $fn)
->hasResponsiveDisplay(): bool
 
// Kam sloupec padne na skládané mobilní kartě (viz Pokročilé → Responzivní rozvržení)
->mobileTitle() ->mobileSubtitle() ->mobileMetric() ->mobileMeta() ->mobileDetail()
TextColumn::make('user')
->mobileDisplayUsing(fn ($record) => $record->name)
->desktopDisplayUsing(fn ($record) => "{$record->name} <{$record->email}>")

Formátování hodnot

->formatStateUsing(Closure $fn) // transformovat hodnotu pro zobrazení
->displayUsing(Closure $fn) // alias pro formatStateUsing
->default(mixed $value) // hodnota, když je stav null
->placeholder(string $text) // text zobrazený, když je hodnota null/prázdná
->limit(int $chars) // zkrátit na N znaků
->prefix(string $prefix) // předřadit text
->suffix(string $suffix) // přidat text
->html(bool $html = true) // vykreslit hodnotu jako raw HTML
->wrap(bool $wrap = true) // povolit zalamování textu (výchozí: nowrap)
TextColumn::make('price')
->prefix("$")
->suffix(' USD')
->placeholder('N/A')
 
TextColumn::make('bio')
->limit(100)
->tooltip(fn ($record) => $record->bio) // zobrazit celé při hoveru
 
TextColumn::make('content')
->html()
->wrap()
->limit(200)

Stylování textu

Použijte ->textSize() pro velikost písma buňky. ->size() (ze sdíleného concernu HasSize) nastaví strukturální velikost sloupce a nemění písmo textu.

->textSize(string $size) // 'xs', 'sm', 'md', 'lg', 'xl' — velikost písma textu
->weight(string $weight) // 'thin', 'light', 'normal', 'medium', 'semibold', 'bold', 'extrabold'
->textColor(string $color) // název Tailwind barvy nebo 'gray', 'primary', atd.
->fontFamily(string $family) // 'sans', 'serif', 'mono' (jen TextColumn)
TextColumn::make('name')
->weight('bold')
->textSize('lg')
 
TextColumn::make('subtitle')
->textSize('sm')
->textColor('gray')
->weight('light')

Šířka a zarovnání

->width(string $width) // CSS šířka: '200px', '20%', 'auto'
->alignment(string $alignment) // 'left', 'center', 'right'
->alignLeft() // zkratka
->alignCenter() // zkratka
->alignRight() // zkratka

Ikony

->icon(string|Icon|Closure|null $icon, ?string $position = 'before') // pozice: 'before' | 'after'
->color(string|Color $color) // barva sloupce: text a ikona, pokud nemá vlastní
->iconColor(string|Color|Closure|null $color) // barva ikony pro každý záznam — role, nebo closure, která ji vrátí
->iconTile(bool $tile = true) // posadit ikonu do tónované dlaždice — kotva řádku v seznamu

Na seznamu (layout('list')) sáhněte i po iconTile(): holá tónovaná ikona stačí na mřížce sloupců, kde je řádek už tak řada zarovnaných hodnot — ale tam, kde je záznam věta, dá teprve dlaždice řádkům levou hranu, po které oko sjíždí. Pozadí i ikona přicházejí z jedné role, takže se nemohou rozejít, a dlaždici dostanou jen sémantické role — surový odstín o druhu nic neříká, takže padne na neutrální.

color() se resolvuje jednou pro celý sloupec, což je správně pro tón textu a špatně pro stavovou ikonu, jejímž celým úkolem je lišit se řádek od řádku. Na to je iconColor(): předejte roli ze sdíleného slovníku, nebo closure nad záznamem. Closure se vzdá statického mema ikony — stejná cena, jakou už platí closure v icon(), a důvod, proč ani jedno není výchozí.

TextColumn::make('state')
->icon(fn ($record) => $record->failed ? 'x-circle' : 'check-circle')
->iconColor(fn ($record) => $record->failed ? 'danger' : 'success')
 
TextColumn::make('email')
->icon('mail', 'before')
->color('primary')

URL (klikatelná buňka)

->actionUrl(Closure $url, bool $openInNewTab = false) // udělat z buňky odkaz
TextColumn::make('name')
->actionUrl(fn ($record) => route('users.show', $record), openInNewTab: true)
->color('primary')

Kopírovatelné

->copyable(bool $copyable = true) // ikona kopírování kliknutím
->copyMessage(string $msg) // text zpětné vazby po zkopírování

Tooltip a popis

->tooltip(string|Closure $tooltip) // tooltip při hoveru
->description(string|Closure $desc) // sekundární text pod hodnotou
TextColumn::make('title')
->description(fn ($record) => Str::limit($record->body, 50))
->tooltip(fn ($record) => "Created: {$record->created_at->format('d.m.Y')}")

Souhrn (agregátní patička)

->summarize(string $aggregate, ?string $label = null)

Dostupné agregáty: 'sum', 'avg', 'count', 'min', 'max', 'range'

Detaily viz Pokročilé — Souhrn.

Extra HTML atributy

->extraAttributes(array $attrs) // na <td>
->extraHeaderAttributes(array $attrs) // na <th>
TextColumn::make('notes')
->extraAttributes(['data-testid' => 'notes-cell'])
->extraHeaderAttributes(['class' => 'bg-gray-100'])

Pivot sloupce

->pivot(bool $isPivot = true) // označí jako sloupec pivot tabulky
->isPivot(): bool

Pro many-to-many relace s pivot daty:

TextColumn::make('roles.pivot.assigned_at')
->pivot()
->dateTime('d.m.Y')

Přístup ke stavu

->state(mixed $value) // přepsat hodnotu stavu
->getState(Model $record): mixed // resolvovat stav ze záznamu

Vlastní rendering (Blade partialy)

Každý sloupec vlastní svůj stav/konfiguraci a deleguje markup na Blade partial pod packages/table/resources/views/tables/columns/. Základní textová buňka se vykresluje přes text.blade.php; každý sloupec s custom-UI má svůj vlastní partial (badge, boolean, icon, image, button, toggle, poll, split, stacked, select, text-input-*). Sloupce nikdy nevrací inline HTML z renderCell() — volají renderView('tables.columns.<name>', [...]).

Dva způsoby přizpůsobení markupu:

// 1. Přepis u jednotlivých sloupců — nasměrujte jakýkoli sloupec na svůj vlastní Blade pohled.
TextColumn::make('name')->view('columns.my-name-cell');
 
// 2. Přepis pro celý projekt — publikujte pohledy balíčku a upravte partial.
// php artisan vendor:publish --tag=wire-table::views
// pak upravte resources/views/vendor/wire-table/tables/columns/badge.blade.php

Pořadí resolvování pohledu: explicitní ->view() vyhrává, pak pohled balíčku (wire-table::tables.columns.<name>), pak app-level pohled stejného názvu. Váš partial dostane přesně ta data jako vestavěný — už resolvované primitivy stavu/konfigurace pro daný sloupec — takže přepisujete jen HTML.