Conditional logic in Laravel forms: when fields should show (and hide) | FilaForms                                 [ ![Filaforms Logo](https://filaforms.app/logo.svg)FilaForms

 ](https://filaforms.app)  [ Features ](https://filaforms.app#features) [ Pricing ](https://filaforms.app#pricing) [ Blog ](https://filaforms.app/blog) [ Documentation ](https://docs.filaforms.app)  [ Try Demo ](https://filaforms.app/login) [ Get Started ](https://filaforms.app#pricing)

 [ Features ](https://filaforms.app#features) [ Pricing ](https://filaforms.app#pricing) [ Blog ](https://filaforms.app/blog) [ Documentation ](https://docs.filaforms.app) [ Try Demo ](https://filaforms.app/login) [ Get Started ](https://filaforms.app#pricing)

   ![FilaForms](https://filaforms.app/logo.svg) FilaForms

 TutorialsConditional logic in Laravel forms: when fields should show (and hide)
======================================================================

 filaforms.app/blog

  [    Back to blog ](https://filaforms.app/blog) [ Tutorials ](https://filaforms.app/blog/category/tutorials)

Conditional logic in Laravel forms: when fields should show (and hide)
======================================================================

 Manuk Minasyan ·  March 30, 2025  · 6 min read

 A job application form asks "Do you have a work permit?" If yes, move on. If no, show a field asking which visa type they'd apply for. Simple concept, surprisingly annoying to implement well.

Conditional logic is what separates a dumb form from a smart one. Fields that appear based on previous answers make forms shorter and less intimidating — especially in [multi-step forms](https://filaforms.app/blog/multi-step-forms-in-filament-a-complete-guide) where entire steps can be hidden. But wiring them up in Laravel requires more thought than most tutorials let on.

The basics: Filament's reactive forms
-------------------------------------

Filament has built-in support for conditional fields using the `->live()` modifier and `->visible()` / `->hidden()` callbacks.

Here's a straightforward example:

```
Select::make('employment_status')
    ->options([
        'employed' => 'Employed',
        'self_employed' => 'Self-employed',
        'unemployed' => 'Unemployed',
        'student' => 'Student',
    ])
    ->live()
    ->required(),

TextInput::make('company_name')
    ->visible(fn (Get $get) => in_array($get('employment_status'), ['employed', 'self_employed']))
    ->required(fn (Get $get) => in_array($get('employment_status'), ['employed', 'self_employed'])),

TextInput::make('university')
    ->visible(fn (Get $get) => $get('employment_status') === 'student')
    ->required(fn (Get $get) => $get('employment_status') === 'student'),

```

The `->live()` modifier tells Filament to send the field value to the server on every change. The `->visible()` callback runs on the server and determines whether to render the field.

This works. But there are a few things to know.

Server round-trips
------------------

Every time someone changes a `->live()` field, Livewire sends a request to the server. On a fast connection with a nearby server, the delay is barely noticeable. On a slow mobile connection, there's a visible flicker as conditional fields appear or disappear.

You can control the debounce:

```
Select::make('employment_status')
    ->live(debounce: 500) // wait 500ms after the last change

```

Or use `->live(onBlur: true)` to only trigger when the user leaves the field. This reduces requests but means conditional fields don't appear until the user tabs away.

For public-facing forms where users might be on mobile, `onBlur: true` is usually the better default. For admin panel forms where you control the network environment, immediate reactivity is fine.

Common conditional patterns
---------------------------

### Show/hide based on a selection

The most common pattern. A dropdown or radio button controls which fields appear.

```
Radio::make('contact_preference')
    ->options([
        'email' => 'Email',
        'phone' => 'Phone',
        'mail' => 'Physical mail',
    ])
    ->live()
    ->required(),

TextInput::make('phone_number')
    ->tel()
    ->visible(fn (Get $get) => $get('contact_preference') === 'phone')
    ->required(fn (Get $get) => $get('contact_preference') === 'phone'),

Textarea::make('mailing_address')
    ->visible(fn (Get $get) => $get('contact_preference') === 'mail')
    ->required(fn (Get $get) => $get('contact_preference') === 'mail'),

```

Note: the email field doesn't need a conditional because you're probably already collecting it.

### Show additional fields based on a checkbox

```
Toggle::make('has_dietary_requirements')
    ->label('Do you have dietary requirements?')
    ->live(),

Textarea::make('dietary_details')
    ->label('Please describe your dietary requirements')
    ->visible(fn (Get $get) => $get('has_dietary_requirements'))
    ->required(fn (Get $get) => $get('has_dietary_requirements')),

```

### Cascading selects

Field B's options depend on field A's value. Country → State is the classic example.

```
Select::make('country')
    ->options([
        'us' => 'United States',
        'ca' => 'Canada',
        'uk' => 'United Kingdom',
    ])
    ->live()
    ->afterStateUpdated(fn (Set $set) => $set('state', null))
    ->required(),

Select::make('state')
    ->options(function (Get $get) {
        return match ($get('country')) {
            'us' => ['ca' => 'California', 'ny' => 'New York', 'tx' => 'Texas'],
            'ca' => ['on' => 'Ontario', 'bc' => 'British Columbia', 'qc' => 'Quebec'],
            'uk' => ['eng' => 'England', 'sco' => 'Scotland', 'wal' => 'Wales'],
            default => [],
        };
    })
    ->visible(fn (Get $get) => filled($get('country')))
    ->required(),

```

The `afterStateUpdated` callback resets the state field when the country changes, so you don't end up with "California, Canada."

### Conditional validation

Sometimes you want the field to always be visible but validation rules change based on context:

```
TextInput::make('budget')
    ->numeric()
    ->required()
    ->minValue(fn (Get $get) => $get('project_type') === 'enterprise' ? 10000 : 0),

```

The validation trap
-------------------

Here's a mistake that catches people: making a field conditionally visible but always required.

```
// Bug: field is hidden but still required
TextInput::make('company_name')
    ->visible(fn (Get $get) => $get('is_employed'))
    ->required(), // This validates even when hidden!

```

The fix is to make the requirement conditional too:

```
TextInput::make('company_name')
    ->visible(fn (Get $get) => $get('is_employed'))
    ->required(fn (Get $get) => $get('is_employed')),

```

If you forget this, users who don't see the field will get validation errors they can't fix. They'll submit the form, get "company name is required," and have no idea where that field is because it's hidden for their selection.

Conditional logic without code
------------------------------

All of the above requires PHP. You're writing closures, referencing field names as strings, and hoping the `Get` calls return what you expect.

For developers, this is fine. But if you want a non-developer to be able to set up "show field X when field Y equals Z," code isn't the answer — one of the reasons [every Laravel app eventually needs a form builder](https://filaforms.app/blog/why-every-laravel-app-needs-a-form-builder-not-just-code).

[FilaForms](https://filaforms.app) lets you configure conditional logic in the visual form builder. When adding a field, you set visibility rules through the UI: "Show this field when \[Employment Status\] is \[Employed\]." No closures, no PHP, no deployment.

This matters for forms that change often. A survey that gets updated quarterly, a registration form that varies by event — if the person making changes isn't a developer, visual conditional logic removes a bottleneck.

Testing conditional forms
-------------------------

Conditional forms have more states than they look. A form with three conditional branches doesn't have one happy path — it has at least four (three branches plus the case where no condition triggers).

For each conditional field, test:

- The field appears when the condition is met
- The field disappears when the condition is not met
- Validation runs only when the field is visible
- Changing the trigger field back and forth doesn't leave stale data
- The submission contains the right data for each path

Laravel Dusk or Livewire's testing utilities handle this. But write the tests. Conditional forms are where "it works on my machine" goes to die.

Keep it simple
--------------

The temptation with conditional logic is to build tangled decision trees. Field A controls field B, which controls field C, which controls fields D and E. Three levels deep, and nobody, including you in six months, can follow the logic.

If your conditional logic needs a flowchart to explain, the form is probably too complex. Split it into separate forms, or rethink what you're asking.

The best conditional forms have one level of depth: a trigger field and a handful of dependent fields. That's it. Your users get a form that feels straightforward, and you get code you can still understand in six months.

 Related posts
-------------

 [  Tutorials   May 22, 2026

 Stop Spam in Laravel Forms: Honeypot, Rate Limits, and Smarter Defaults
-------------------------------------------------------------------------

reCAPTCHA isn't the answer. Or at least, it's not the first answer. Here's the layered approach we use to keep junk out of FilaForms submissions.

 ](https://filaforms.app/blog/stop-spam-laravel-forms-honeypot-rate-limits) [  Tutorials   Apr 30, 2026

 File Uploads in Filament Forms: Storage, Validation, and Security
-------------------------------------------------------------------

File uploads are where most form builders cut corners. They'll let you add a file field and call it done, leaving you to figure out storage and validation

 ](https://filaforms.app/blog/file-uploads-in-filament-forms-storage-validation-and-security) [  Tutorials   Mar 27, 2025

 Multi-step forms in Filament: a complete guide
------------------------------------------------

How to build multi-step forms in Laravel with Filament — wizard components, progress tracking, conditional steps, and where most implementations go wrong.

 ](https://filaforms.app/blog/multi-step-forms-in-filament-a-complete-guide)

    ![FilaForms Logo](/logo.svg) FilaForms

 Laravel form infrastructure for Filament. Stop rebuilding forms on every project.

 ### Product

 [ Features ](https://filaforms.app#features) [ Documentation ](https://docs.filaforms.app) [ Blog ](https://filaforms.app/blog) [ Pricing ](https://filaforms.app#pricing) [ Contact ](mailto:hello@filaforms.app)

 ### Legal

 [ Terms of Service ](https://filaforms.app/terms-of-service) [ Privacy Policy ](https://filaforms.app/privacy-policy)

  © 2025-2026 FilaForms. All rights reserved.

 [    ](mailto:hello@filaforms.app) [    ](https://x.com/MinasyanManuk)
