Skip to content
laravel-nova-examples.com

Show, hide and require fields conditionally with dependsOn

Use Nova's dependsOn to reveal a field, make it required or read-only based on another field's value, without writing a custom Vue component.

Nova
5.x
Published
Reading time
3 min

A common admin form requirement: an order can be a personal purchase or a gift, and only gifts need a recipient email. The recipient field should be hidden for personal purchases and required for gifts.

Nova solves this with dependent fields. A field declares which other fields it depends on, and Nova re-evaluates its callback every time one of those fields changes in the form.

The resource fields

use Laravel\Nova\Fields\FormData;
use Laravel\Nova\Fields\ID;
use Laravel\Nova\Fields\Select;
use Laravel\Nova\Fields\Text;
use Laravel\Nova\Http\Requests\NovaRequest;

public function fields(NovaRequest $request): array
{
    return [
        ID::make()->sortable(),

        Select::make('Purchase Type', 'type')
            ->options([
                'personal' => 'Personal',
                'gift' => 'Gift',
            ])
            ->rules('required'),

        Text::make('Recipient Email', 'recipient_email')
            ->hide()
            ->rules('nullable', 'email')
            ->dependsOn(['type'], function (Text $field, NovaRequest $request, FormData $formData) {
                if ($formData->type === 'gift') {
                    $field->show()->rules('required', 'email');
                }
            }),
    ];
}

How it works

  • dependsOn(['type'], ...) takes the attribute names of the fields to watch, not their labels. Here the Select is created with the attribute type, so that is what you pass.
  • The callback receives the field instance, the current request and a FormData object with the values currently in the form.
  • The field starts hidden via hide(). When the callback runs and the type is gift, show() reveals it and the rules are replaced with required.

The callback runs both while the user edits the form and when the form is submitted, so the required rule is enforced on the server as well. You do not need a separate validation rule like required_if.

Read-only instead of hidden

Sometimes users should see a value but only edit it in a specific state. Swap hide()/show() for readonly():

Text::make('Recipient Email', 'recipient_email')
    ->readonly()
    ->dependsOn(['type'], function (Text $field, NovaRequest $request, FormData $formData) {
        if ($formData->type === 'gift') {
            $field->readonly(false)->rules('required', 'email');
        }
    }),

Checking boolean fields

Values in FormData come from the submitted form, so do not compare a Boolean field's value to true directly. Use the boolean() helper, which casts the value for you:

->dependsOn('anonymous', function (BelongsTo $field, NovaRequest $request, FormData $formData) {
    if ($formData->boolean('anonymous') === false) {
        $field->show()->rules('required');
    }
}),

Common pitfalls

  • Forgetting the default state. Rules set before dependsOn() apply whenever the condition is not met. Keep them permissive (nullable) and tighten them inside the callback.
  • Watching the label instead of the attribute. dependsOn(['Purchase Type']) silently never fires.
  • Heavy queries in the callback. The callback runs on every change of the watched field. Keep database queries in it small.

Reference