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 Charcounted Fields Laravel Package

elevate-digital/nova-charcounted-fields

A Laravel Nova package that adds character-counted text fields with live counts and length-limit support. Ideal for titles, excerpts, meta descriptions, and other constrained content, helping editors stay within required limits while composing in Nova. Easy to configure and integrate into existing r...

View on GitHub
Deep Wiki
Context7

Getting Started

elevate-digital/nova-charcounted-fields is a small Nova field package that swaps the stock Text and Textarea components for versions that render a live character counter under the input. It is not a validation library — it is a UX affordance — so treat it as presentation sugar layered on top of normal Nova fields.

Minimal setup:

composer require elevate-digital/nova-charcounted-fields

There is usually no service provider to register manually (Laravel package discovery handles it), but if the package ships compiled assets run php artisan nova:publish afterward. Confirm the Nova major version constraint in the package's composer.json before installing — small field packages frequently lag behind Nova releases.

Where to look first:

  • src/ — the field classes. You will almost certainly find two classes extending Laravel\Nova\Fields\Text and Laravel\Nova\Fields\Textarea; note the exact namespace and class names, since they are what you import in your resources.
  • resources/js/ (or dist/js/) — the Vue component that actually draws the counter. Skim it to see how the limit is passed through meta.
  • README.md — the option name for setting the limit (maxlength, max, or a bespoke charLimit). This is the one detail you must get right; everything else behaves like a normal Nova field.

First use case: SEO and social metadata. A Meta Title (≈60 chars) and Meta Description (≈160 chars) pair is the canonical reason to install this, because editors need to see the budget while typing, not after a validation error.

use ElevateDigital\CharCountedFields\CharCountedText;
use ElevateDigital\CharCountedFields\CharCountedTextarea;

public function fields(NovaRequest $request): array
{
    return [
        CharCountedText::make('Meta Title')
            ->rules('required', 'max:60')
            ->maxlength(60),

        CharCountedTextarea::make('Meta Description')
            ->rules('nullable', 'max:160')
            ->maxlength(160)
            ->rows(3),
    ];
}

Implementation Patterns

Drop-in replacement, not a wrapper. Use these classes exactly where you would use Text::make() or Textarea::make(). Every standard Nova chain method (rules, nullable, required, help, placeholder, hideFromIndex, onlyOnForms, default, resolveUsing) still applies because they inherit from the core fields. Resist the urge to wrap them in a custom Field subclass unless you need to change behaviour.

Keep validation separate. The counter is advisory; the rule is authoritative. Always pair the field with ->rules('max:160') (or a dedicated Rule object) so the limit survives API writes, imports, and Nova actions that bypass the form. Set the database column length to match — the counter is not a substitute for schema constraints.

Centralise the limits. Repeated magic numbers rot. Define constants or a small factory so the limit and rule can never drift apart:

private const META_DESCRIPTION_MAX = 160;

CharCountedTextarea::make('Meta Description')
    ->maxlength(self::META_DESCRIPTION_MAX)
    ->rules('nullable', 'max:' . self::META_DESCRIPTION_MAX)
    ->help('Aim for 150–160 characters so search engines do not truncate.'),

Group with layout primitives. These fields compose normally inside Panel, Tab, and Fieldset, which is useful when a resource has several length-sensitive fields (title, slug, summary, description) that you want visually adjacent so editors can see all the counters at once.

Control visibility per context. Counters only make sense on forms. On index and detail views the field falls back to plain text rendering, but you can be explicit with ->hideFromIndex() or ->onlyOnForms() to save column width in dense index tables.

Consider reuse in actions and inline creation. Nova actions that surface fields, and Laravel\Nova\Fields inside modal forms, generally accept these classes too. Verify the counter renders inside the action modal — component registration in the Nova asset pipeline is the usual failure point there.

Extend narrowly if you need defaults. If every textarea in your app should have a counter, subclass once and set the component, limit, and rows in the constructor, then use your own class in resources. That keeps vendor namespaces out of fifty resource files and makes swapping the package later a one-file change.

Gotchas and Tips

  • The counter is client-side only. It will happily let a determined user paste past the limit unless the underlying input carries a hard maxlength attribute. Decide deliberately whether you want a soft warning counter or a hard block, and make sure the field metadata matches that intent.
  • Emoji and multibyte strings disagree. JavaScript .length counts UTF-16 code units, so an emoji counts as 2; PHP's mb_strlen counts it as 1. A field showing 158/160 in the browser can still pass or fail a max:160 rule differently than expected. Test near the boundary with accented characters, CJK text, and emoji before shipping a hard limit.
  • Asset pipeline issues are the usual "it does nothing" cause. If the counter does not appear, check the browser console for a failed component load, run php artisan nova:publish, then php artisan optimize:clear. Nova caches its compiled manifest aggressively; a stale manifest is the most common culprit after a package upgrade.
  • Version-pin against your Nova major. With zero dependents and no visible maintenance signal, upgrade risk sits entirely with you. Pin an exact version in composer.json and re-test after any Nova upgrade rather than floating to ^1.0.
  • Audit the source before adopting. The package is tiny — the Vue component and two PHP classes are readable in ten minutes. Confirm what meta it sends to the front end, whether it uses strlen anywhere server-side, and whether the counter re-syncs correctly when Nova repopulates a form after a validation error. The last one is a common rough edge in small field packages.
  • Debugging the meta. If the limit is not reaching the component, use ->withMeta(['foo' => 'bar']) on the field and inspect the props in Vue DevTools to confirm how the package expects configuration to be passed.
  • Have an exit plan. If the package breaks on a future Nova release, the replacement is roughly thirty lines: a Vue component that binds value.length to a <span> and a PHP class setting ->component(). Because these fields are drop-in replacements, migrating away is a search-and-replace in resource files, not a rewrite — which is exactly why you should keep the vendor class names confined to as few files as possible.
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.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
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
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core