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

Nova Tags Input Laravel Package

whchi/nova-tags-input

A Laravel Nova field that adds a tag-style input to your resources, letting users type, select, and create multiple tags in one place. Configurable suggestions and simple storage make it easy to attach array-based tags to any model.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a thin Nova field wrapper around JohMun's vue-tags-input. It gives you a tag-entry UI in Nova forms and stores the value as a JSON array of { text: "..." } objects. Before you install anything, note the metadata: archived, 2 stars, 0 dependents. Treat this as a reference implementation or short-term stopgap, not a long-term dependency.

First steps:

  1. Verify Nova compatibility before writing code. Check the package's composer.json (laravel/nova constraint) and its package.json (vue-tags-input version). If the field is pinned to [email protected], it targets Vue 2 and therefore Nova 3 and earlier. Nova 4/5 run Vue 3 and need [email protected]. This one check will save you an afternoon.

  2. Install into an existing Nova app:

    composer require whchi/nova-tags-input
    php artisan nova:publish   # if the package ships assets you need to publish
    

    Confirm the compiled field JS actually landed in public/vendor/... — archived Nova packages frequently ship stale dist/ bundles.

  3. Look first at vendor/whchi/nova-tags-input/resources/js/components/FormField.vue and field.js. That is the whole package: a FormField mixin, a DetailField, and a vue-tags-input binding. Reading ~150 lines tells you everything about the data shape and available meta options.

  4. First use case: tagging a Post.

    // app/Nova/Post.php
    use Whchi\NovaTagsInput\Tags; // confirm exact class/namespace in the vendor dir
    
    public function fields(Request $request)
    {
        return [
            ID::make()->sortable(),
            Text::make('Title'),
            Tags::make('Tags'),
        ];
    }
    
    // migration
    $table->json('tags')->nullable();
    
    // app/Models/Post.php
    protected $casts = ['tags' => 'array'];
    

    If the field renders but the value round-trips as null, the problem is almost always the cast or a prepareForValidation mismatch — see Gotchas.

Implementation Patterns

Store as JSON, not CSV. vue-tags-input emits an array of objects, so a json column plus an array cast is the only shape that round-trips without a custom accessor. If you inherit a comma-separated column, normalize in the model rather than patching the field:

public function setTagsAttribute($value)
{
    $this->attributes['tags'] = json_encode(
        collect($value)->map(fn ($t) => is_array($t) ? $t['text'] : $t)->values()->all()
    );
}

Wrap it in a factory method so you can change the underlying implementation later without touching every resource:

// app/Nova/Fields/TagField.php
public static function make(string $name = 'Tags')
{
    return Tags::make($name)->help('Press Enter or comma to add a tag.');
}

Autocomplete from existing tags. If the field exposes a suggestions meta key (check FormField.vue for this.field.* reads), populate it from the DB in fields():

Tags::make('Tags')
    ->withMeta(['suggestions' => Post::query()
        ->pluck('tags')->flatten(1)->pluck('text')->unique()->values()])

If no such hook exists upstream, that's your first local patch — a 3-line computed property in FormField.vue plus a withMeta call. Because the package is archived, patching the vendor copy (with a fork or a path repository) is a legitimate pattern here.

Query by tag with MySQL/Postgres JSON operators:

Post::whereJsonContains('tags', [['text' => 'laravel']])->get();

Detail and index views need different formatting than the form. Override resolve/displayUsing or add a small accessor so the index shows laravel, nova, php instead of [{"text":"laravel"}]:

public function resolve($resource, $attribute = null)
{
    parent::resolve($resource, $attribute);
    $this->value = collect($resource->{$this->attribute} ?? [])
        ->pluck('text')->implode(', ');
}

Pair it with server-side validation on the resource or form request — the field's own validation is client-only:

'tags' => ['array'],
'tags.*.text' => ['string', 'max:32'],

Consider the built-in first. Nova ships Laravel\Nova\Fields\Tags (since Nova 2). If you only need free-text tags with index/detail rendering, use it. Reach for nova-tags-input only when you specifically want vue-tags-input's UX: inline validation styling, delimiter control, autocomplete dropdown, and tag-level ti-* CSS hooks for theming.

Gotchas and Tips

  • Archived = frozen. Do not add this to a new project's composer.json without forking it. composer require will work, but there will be no security patches, no Nova 5 fixes, and no Vue 3 migration. Score it as "read once, fork if needed."
  • Vue 2 vs Vue 3 is the killer. Nova 4+ uses Vue 3; [email protected] does not. If the bundled field fails with a blank form area and no console error beyond a Vue warn, check the browser console for Cannot read properties of undefined (reading 'extend') or similar — that's a Vue 2 component inside a Vue 3 host.
  • Data shape mismatch. vue-tags-input wants [{ text: 'foo' }]; almost every other Laravel tagging solution (Spatie's HasTags, Nova's native Tags) uses ['foo', 'bar']. Decide on one canonical shape at the DB layer and convert at the boundary. Half the bugs with this package are shape-conversion bugs.
  • Rebuild assets after any patch. Editing resources/js/ does nothing until you run npm run dev in the package directory and copy dist/ back. Most archived Nova packages ship a dist/ that no longer matches resources/.
  • null vs []. An empty tag list comes back as [] but Nova's FormField default may submit null. Add $table->json('tags')->nullable() and a ?? [] in your accessor, or whereJsonContains on an empty column will silently return nothing.
  • No index sorting. You cannot ->sortable() a JSON tag column meaningfully. If filtering/sorting by tag is a requirement, model tags as a proper pivot table and use a BelongsToMany field for selection, with this field only as a free-form overlay.
  • Debugging tip: php artisan nova:field in Nova 4+ scaffolds a modern Vue 3 field in ~30 seconds. When this package breaks, replacing it with a generated field that imports vue-tags-input@2 is usually faster than diagnosing it — and that's the honest recommendation given the maintenance signal.
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.
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
adachsoft/api-version-bundle