Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Dynamic Field Laravel Package

ajmariduena/dynamic-field

Dynamic Field for Laravel lets you attach custom fields to Eloquent models without writing new migrations. Configure field types, validation, and options, store values as JSON, and access dynamic data through a simple, fluent API—ideal for user-defined forms and flexible schemas.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install and confirm discovery. Require it like any Nova field, then check that Nova picks up the service provider automatically:

    composer require ajmariduena/dynamic-field
    php artisan nova:field ajmariduena/dynamic-field  # only if you intend to vendor the assets
    

    Nova 4/5 auto-discovers providers via extra.laravel.providers in the package's composer.json. If the field does not appear in the browser, run php artisan nova:publish and hard-refresh — a missing compiled js/field.js is the usual culprit.

  2. Read three files before anything else.

    • src/DynamicField.php — the PHP field class. This is where the public API lives (make(), whatever setter methods it exposes, and any resolve/fill callbacks).
    • resources/js/field.js — the registered Vue component name. Note the exact string, because ->component('...') must match it.
    • resources/js/components/FormField.vue — tells you which other fields the component subscribes to and what shape of data it expects. This is the whole contract of a "dynamic" field.
  3. First use case: one field driving another. The canonical scenario for a field like this is a select/text input whose options, visibility, or even input type change based on a sibling field's value. Start with a two-field resource:

    use Ajmariduena\DynamicField\DynamicField; // verify namespace against src/
    
    public function fields(NovaRequest $request)
    {
        return [
            Select::make('Type')->options([
                'text'   => 'Free text',
                'select' => 'Picklist',
            ]),
    
            DynamicField::make('Value')
                ->dependsOn('type')          // confirm the actual method name in src/
                ->options(fn () => /* ... */),
        ];
    }
    

    Get that single field reacting to a value change before you try anything clever with closures, validation, or index-view rendering.

Implementation Patterns

Closure-backed configuration. Dynamic fields exist so that configuration is evaluated per-request rather than at field-definition time. Put anything request-dependent (current user, $request->resourceId, related model state) inside a closure passed to options(), dependsOn(), or a resolveUsing()-style hook. Anything that is static should stay a plain array — closures are re-evaluated on every serialization and are the first thing to profile when a resource form gets slow.

Dependent selects. The most common production pattern is a cascading pair (country → city, project → task). Keep the dependency graph one level deep on the field itself and do the filtering server-side:

DynamicField::make('City')
    ->dependsOn('country')
    ->options(fn (NovaRequest $request) => City::where('country_id', $request->country)->pluck('name', 'id'));

Reach for Nova's own dependsOn() / DependsOn container before duplicating that behaviour inside the dynamic field — the package is worth using when the input type changes, not just the options.

Type-switching inputs. If the field renders a different control based on a discriminator (text vs. number vs. select), mirror that logic on the PHP side in rules(). Nova's validation runs against whatever the field declares, so a field that can be either a string or an integer needs conditional rules:

->rules(fn (NovaRequest $request) => $request->type === 'number'
    ? ['required', 'numeric']
    : ['required', 'string', 'max:255'])

Reusable presets. Rather than copy-pasting DynamicField::make()->dependsOn()->options() across resources, extract a small helper (a static factory or a custom Nova field wrapping this one). This package is low-level; most teams end up writing a thin domain-specific wrapper like StatusField or CascadingSelect and hiding the raw DynamicField behind it.

Where it fits relative to other Nova features. If what you need is a field that only shows or hides, use ->hideWhen() / ->showWhen() — no extra package needed. If you need a display-only computed value, Text::make(...)->resolveUsing() already covers it. Use DynamicField when the component itself has to change, or when option sets are genuinely request-dependent and large enough that you don't want them inlined in the field definition.

Gotchas and Tips

  • Verify the namespace and API before writing code against it. This repository has a single-digit star count and no dependents, so treat the README as a hint rather than a spec. Read src/DynamicField.php end-to-end; the public method names (dependsOn, options, resolveUsing, whatever they actually are) are the real documentation.
  • Nova major-version drift. Nova 4 and Nova 5 changed the field mixins (FormField, HandlesValidationErrors) and Vue 3 migration. A package this small may have been built against one and not tested against the other. Check composer.json for the laravel/nova constraint and package.json for Vue 2 vs 3 before you build a workflow on top of it.
  • Reactivity is on you. The PHP side of a dynamic field is stateless between requests; the Vue component must watch the dependency field and re-render. If the field renders correctly on page load but does not update when the sibling changes, the bug is in the component's watcher, not in your fields() method.
  • Index and detail views rarely work out of the box. Dynamic option closures can't be invoked during indexQuery serialization the same way they are on forms. Expect to add ->onlyOnForms(), or an explicit ->resolveUsing() for the index representation, otherwise you'll see raw IDs in the resource table.
  • Asset caching. After any change to the field's Vue files, re-run php artisan nova:publish and hard-refresh. Stale compiled assets produce the maddening "component not found" error that looks like a PHP problem but isn't.
  • Debugging order. 1) Is the component name registered? (browser console → Vue devtools) 2) Is the field serialized with the meta you expect? (Nova.request() in the console, or dump in resolve) 3) Is the watcher firing? Add a console.log in watch.
  • Extension points to prefer over forking. The component registered via ->component() can be swapped for your own, and resolveUsing/fillUsing cover most behavioural variance. Forking the package for a one-line change is rarely worth it — vendor it under your own namespace if you must patch it, since upstream maintenance is uncertain.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console