Formuláře
Wire Forms
Formulářový systém: schéma deklarované v PHP, navázané na Livewire hostitele nebo samostatné, a co se děje mezi odesláním a uloženým záznamem.
Vnořené řádky s ovládáním přidat, odebrat a přeřadit.
Na této stránce
- Instalace
- Jak formuláře fungují
- Jeden formulář
- Více formulářů
- Explicitní registrace formulářů
- Režimy modelu
- Samostatné použití (bez Livewire)
- Reference Form API
- Schéma a stav
- Model a uložení
- Hooky životního cyklu uložení
- Notifikace
- Validace
- Stav
- Autorizace
- Introspekce
- Rendering
- Factory
- Livewire vazba
- Trait WithForms
- Typy polí
- Vstupní pole
- Layoutové komponenty
- Zobrazovací komponenty
- Postavte si vlastní
- Sdílené API pole
- Úprava formuláře, který nevlastníte
Samostatný systém formulářů pro Laravel Livewire. Funguje nezávisle nebo s Wire Table.
Potřebujete záznam zobrazit read-only místo editace? Viz Infolisty — stejné schéma a layout, jen se zobrazovacími entries místo vstupních polí.
Instalace
composer require nyoncode/wire-forms
Přidejte do Tailwind content cest:
export default { content: [ // ...aktuální cesty aplikace './vendor/nyoncode/wire-core/resources/views/**/*.blade.php', './vendor/nyoncode/wire-forms/resources/views/**/*.blade.php', ]}
Jak formuláře fungují
Definujte schéma Form na své Livewire komponentě, navažte ho na state path a vykreslete pomocí {{ $this->form }}.
Jeden formulář
use NyonCode\WireForms\Forms\Form;use NyonCode\WireForms\Forms\WithForms;use NyonCode\WireForms\Components\TextInput; class CreateUser extends Component{ use WithForms; public ?array $data = []; public function form(Form $form): Form { return $form ->statePath('data') ->model(User::class) ->schema([ TextInput::make('name')->required(), TextInput::make('email')->email()->required(), ]) ->successMessage('User created'); } public function save(): void { $this->form->save(); }}
<form wire:submit="save"> {{ $this->form }} <button type="submit">Create</button></form>
Více formulářů
Metody končící na Form se automaticky detekují:
class UserSettings extends Component{ use WithForms; public array $profileData = []; public array $passwordData = []; public function profileForm(Form $form): Form { return $form ->statePath('profileData') ->model($this->user) ->schema([ TextInput::make('name')->required(), TextInput::make('bio'), ]); } public function passwordForm(Form $form): Form { return $form ->statePath('passwordData') ->schema([ TextInput::make('current_password')->password()->required(), TextInput::make('password')->password()->required()->rules(['confirmed']), TextInput::make('password_confirmation')->password()->required(), ]); } public function saveProfile(): void { $this->profileForm->save(); } public function savePassword(): void { $data = $this->passwordForm->validate(); $this->user->update(['password' => Hash::make($data['password'])]); }}
<form wire:submit="saveProfile"> {{ $this->profileForm }} <button type="submit">Save Profile</button></form> <form wire:submit="savePassword"> {{ $this->passwordForm }} <button type="submit">Change Password</button></form>
Explicitní registrace formulářů
Alternativa k automatické detekci — vraťte názvy metod přesně tak, jak jsou definované:
protected function getForms(): array{ return ['profileForm', 'passwordForm'];}
Režimy modelu
// Create mód — Form::save() volá User::create($data)$form->model(User::class); // Edit mód — Form::save() volá $user->update($data)$form->model($user); // Žádný model — save() vyhodí chybu, ale validate() funguje$form->model(null);
Introspekce:
$form->isCreating(); // true když je model řetězec třídy$form->isEditing(); // true když je model instance$form->getModel(); // instance modelu nebo null
Samostatné použití (bez Livewire)
Funguje pro server-side validaci a zpracování dat:
$form = Form::make() ->schema([ TextInput::make('name')->required()->maxLength(255), TextInput::make('email')->email()->required(), ]) ->state(['name' => 'John', 'email' => 'john@example.com']); // Jen validace$validated = $form->validate(); // při selhání vyhodí ValidationException // Validace + uložení$form->model(User::class)->save();
Reference Form API
Schéma a stav
->schema(array $components) // definice polí->statePath(string $path) // název Livewire vlastnosti pro stav->fill(array $data) // naplnit stav->state(array $data) // alias pro fill()->getState(): array // aktuální stav->getValidationRules(): array // posbíraná pravidla->validate(): array // zvalidovat a vrátit data
Model a uložení
->model(string|Model|null $model) // Eloquent model (třída pro create, instance pro edit)->save(): mixed // celý životní cyklus uložení->using(Closure $fn) // vlastní save callback (nahrazuje výchozí perzistenci)->optimisticLock(?string $column = 'updated_at') // přeruší update, když se záznam změnil od fill
Ochrana proti souběžné editaci viz Životní cyklus ukládání → Optimistic locking.
Hooky životního cyklu uložení
->mutateDataBeforeSave(Closure $fn) // fn(array $data): array — transformovat data před perzistencí->beforeSave(Closure $fn) // fn(array $data): void — běží před perzistencí->afterSave(Closure $fn) // fn(Model|mixed $record): void — běží po perzistenci
Notifikace
->successMessage(string|Closure|null $msg) // vlastní text úspěšné notifikace; Closure dostane $record->disableSuccessNotification() // žádná notifikace po uložení
Validace
->validationMessages(array $msgs) // vlastní validační zprávy
Stav
->disabled(bool $disabled = true) // udělat všechna pole read-only
Autorizace
->authorize(bool $usePolicy = true) // zapnout automatické resolvování policy modelu (create/update)->authorizeUsing(?Closure $callback) // fn(User $user, $record = null): bool — vlastní auth kontrola->canSave(): bool // zda aktuální uživatel smí uložit->isReadOnly(): bool // true když autorizace zamítne uložení
Když je ->authorize() zapnuto, formulář se stane read-only (a skryje tlačítko uložit), pokud aktuální uživatel nemá create nebo update policy oprávnění na modelu.
Introspekce
->isCreating(): bool // model je řetězec třídy->isEditing(): bool // model je instance->getModel(): ?Model // aktuální instance modelu->getFlatComponents(): array // všechny komponenty (ploše)
Rendering
->toHtml(): string // Blade výstup(string) $form // __toString()->nativeSubmit(bool $native = true) // vykreslit pole pro odeslání prohlížečem, ne pro Livewire->submitsNatively(): bool // v jakém režimu pole jsou
Nativní odeslání
nativeSubmit() vykreslí pole pro odeslání formuláře samotným prohlížečem:
každé nese name a value=old(…) místo wire:model a chyby se berou ze
sdíleného bagu $errors. Sáhněte po něm tam, kde koncový bod není váš —
přihlašovací obrazovka odesílající na routu Fortify je to, kvůli čemu vznikl.
Element <form> zůstává vám. Akce, @csrf i odesílací tlačítko jsou rozhodnutí
stránky, takže objekt formuláře vykreslí pole a nic kolem nich:
<form method="POST" action="{{ route('login') }}"> @csrf {{ $credentials }} <button type="submit">{{ __('Sign in') }}</button></form>
Pole musí deklarovat, že to umí, implementací Contracts\SupportsNativeSubmit.
Schéma obsahující pole, které to neumí, vyhodí při renderu
FormConfigurationException a pojmenuje ho — pole navázané jen přes wire:model
totiž nemá name, takže by za něj prohlížeč neodeslal nic a stránka by poslala
prázdnou hodnotu, aniž by o tom kdekoli byla zmínka. Nekvalifikuje se nic, co
potřebuje round trip uprostřed formuláře: live() a reaktivní pole, Select
hledající na serveru, FileUpload, Repeater. Implementují to TextInput,
Checkbox, Hidden a OtpInput — pole, ze kterých jsou složené odhlášené
obrazovky.
Checkbox se váže jinak než input, a to záměrně: nese konstantní value="1"
a odpovídá svou přítomností, protože nezaškrtnuté políčko neodešle vůbec žádný
klíč. Zaškrtnutí se vrací z posledního odeslání, pokud nějaké bylo — samotné
old() totiž nerozezná „odškrtnuto“ od „čerstvá stránka“, takže políčko zapnuté
ve výchozím stavu by se po odškrtnutí tiše zaškrtlo znovu.
Režim se aplikuje na schéma, které se chystá vykreslit, až po doběhnutí
form.configuring — takže pole přidané pluginem se přepne se zbytkem a to, které
nativně odeslat nejde, je odmítnuté, ať bylo deklarované, nebo přidané.
Viz ADR 0036.
Factory
Form::make() // statická factory přes container
Livewire vazba
->livewire(Component $component) // navázat na Livewire komponentu
Trait WithForms
Trait WithForms poskytuje:
- Automatickou detekci — skenuje metody končící na
Forma registruje je - Lazy resolvování — formuláře se staví až při prvním přístupu
- Cachování — instance formulářů jsou cachované po dobu requestu
- Magický přístup k vlastnosti —
$this->profileFormvyresolvuje formulář
class MyComponent extends Component{ use WithForms; // Přístup přes: // $this->form → volá metodu form() // $this->profileForm → volá metodu profileForm() // $this->settingsForm → volá metodu settingsForm()}
Typy polí
Vstupní pole
- TextInput — text, email, heslo, číslo, tel, url
- Textarea — víceřádkový text
- Select — rozbalovací seznam, hledání, více hodnot, relace
- Checkbox — jeden checkbox
- CheckboxList — skupina více checkboxů
- Radio — skupina radio tlačítek
- Toggle — přepínač on/off
- DateTimePicker — jednotné date/time/datetime
- TimePicker — jen čas, výběr ze seznamu slotů
- ColorPicker — výběr barvy
- FileUpload — upload souboru/obrázku
- RichEditor — WYSIWYG editor
- Hidden — skryté pole
Layoutové komponenty
Layoutové a schema komponenty (Grid, Flex, Section, Fieldset, Tabs, Wizard, Callout, Empty State) žijí ve sdílené sekci Schema — stejný slovník používají formuláře, infolisty i modaly.
Zobrazovací komponenty
- Placeholder — statický text
- Alert — alert zpráva
- Html — raw HTML
- ViewField — vlastní Blade pohled
Postavte si vlastní
- Rozšíření formulářů — vlastní pole, zobrazovací komponenty, presety a balíčkování
Sdílené API pole
Každé pole dědí:
->label(string|Closure $label)->helperText(string|Closure $text)->hint(string|Closure $hint)->hintIcon(string $icon)->required(bool|Closure $required = true)->hidden(bool|Closure $hidden = true)->visible(bool|Closure $visible = true)->disabled(bool|Closure $disabled = true)->size('sm'|'md'|'lg'|'xl')->columnSpan(int|string $span) // šířka sloupce v gridu->default(mixed $value) // výchozí hodnota (create mód / chybějící klíče)->defaultOnNull(bool $condition = true) // doplnit výchozí hodnotu i pro null v edit módu->extraAttributes(array $attrs) // HTML atributy->live() // wire:model.live->debounce(int $ms = 500) // přidá .debounce.{ms}ms k vazbě->afterStateUpdated(Closure $callback) // reagovat na změny hodnoty (automaticky zapne live)->rules(string|array $rules) // Laravel validační pravidla->unique(?string $table, ?string $column, bool $ignoreRecord = true, ?Closure $modifyRuleUsing) ->validationMessages(array $messages) // vlastní validační zprávy->formatStateUsing(Closure $fn) // fn ($state, $record) — uložená hodnota do stavu pole ->dehydrated(bool|Closure $condition = true) // false nechá hodnotu mimo záznam->dehydrateStateUsing(Closure $fn) // fn ($state, $record) — hodnota na cestě ven
formatStateUsing() běží při plnění formuláře, dehydrateStateUsing() při
ukládání, obojí až po vlastní transformaci typu pole. Co pole zapíše, popisuje
Životní cyklus uložení, unique()
pak Validace.
Closury visible(), hidden(), disabled() a afterStateUpdated() dostávají live state
accessory ($get, $set, $state). Viz Reaktivní pole.
Úprava formuláře, který nevlastníte
Formulář z nainstalovaného modulu se staví uvnitř kódu, který aplikace nemá, takže tři plugin hooky kolem něj jsou ta cesta dovnitř — jeden na každou fázi a nejsou zaměnitelné:
| Hook | Kdy běží | Sáhněte po něm, když chcete |
|---|---|---|
form.configuring |
jednou, když se ze schématu stává config | přidat nebo odebrat pole |
form.filling |
když fill() naváže hodnoty |
změnit, s čím pole přijde |
form.saving |
po validaci, před perzistencí | změnit, co dorazí do záznamu |
$manager->hook(Hook::FormConfiguring, function (FormConfiguringPayload $payload) { $payload->schema = [...$payload->schema, TextInput::make('crm_id')]; return $payload;}, for: 'users');
form.configuring je protějšek table.composing u tabulky: běží na jediném místě,
kde se ze schématu stává config, a ten je memoizovaný — takže se spustí jednou na
formulář, ne jednou na render. for: zúží callback na jeden formulář — registrovaný
klíč resource, který stránka ukazuje, třída hostitelské komponenty, nebo model — a
bez něj callback běží pro každý formulář v aplikaci.
Celý seznam je v Hooky, kde v pipeline sedí ty dva zbylé pak v Životní cyklus uložení.