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 Checkboxes Field Laravel Package

idez/nova-checkboxes-field

A Laravel Nova field package that adds a checkbox group input to resource forms, letting users select and store multiple options at once. Drop-in checkboxes field with native Nova styling and minimal setup for multi-select values.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. This is a single Nova field: one PHP Field class plus precompiled Vue assets (dist/js/field.js), registered by a service provider with no config, no contracts, no events. It slots into a resource's fields() array like any first-party field and persists to one JSON column on the model. That is the entire architectural surface — there is nothing to integrate with beyond Nova itself, and nothing to extend. For a TPM this reads as a narrow, low-blast-radius dependency: it can only affect the forms where it is explicitly used, and it fails visibly (blank field) rather than subtly corrupting unrelated code.

Integration feasibility. Genuinely a half-day of work in a codebase already running Nova: composer require, a json/text column migration, an array cast, and a field definition. The two things that turn that into a day or more are (a) Nova version compatibility, and (b) confirming what the grouped mode actually stores. Neither is verifiable from the package metadata alone — both require a spike.

Technical risk. The dominant risk is abandonment, not code quality. Last release June 2022, five stars, zero dependents, single maintainer, no test suite in the repo. That predates Nova 4.30+ and all of Nova 5; Nova 4+ moved to Vue 3, so a Vue 2-compiled field installs cleanly and renders a blank cell at runtime. Secondary risks worth naming to stakeholders:

  • No server-side enforcement of options. The field constrains what renders, not what is submitted. A crafted /nova-api payload can persist arbitrary keys, including group labels. Authorization and allow-listing are entirely the consuming team's responsibility.
  • Undocumented value shape for the 1.1.0 grouped feature. Flat array of leaf keys versus nested object mirroring group structure is the difference between a one-line filter and a day of refactoring. This is the single highest-leverage unknown.
  • No test coverage to inherit. Every guarantee you need, you write yourself — realistically one round-trip feature test per field.
  • JSON-column second-order effects. searchable() produces false-positive LIKE matches against the JSON blob, whereJsonContains is dialect-specific (no SQLite), and integer keys round-trip as strings.

Key questions to resolve before committing:

  1. Which Nova major version is in production, and does the compiled bundle mount on it? (Check composer.json's laravel/nova constraint and package.json's Vue version, then actually load the form.)
  2. Does grouped mode store flat leaf keys or a nested structure?
  3. Does the field emit a real array or a JSON string on save?
  4. What does an empty selection submit — [], null, or ''?
  5. Is the grouped UI needed at all, or would native BooleanGroup or Select::multiple() cover it? (Grouped mode is the only capability this package adds over the built-ins; BooleanGroup cannot group.)
  6. Who owns the fork if the maintainer doesn't ship a Nova 5 build?

Integration Approach

Stack fit. Assumes Laravel + Nova with a relational database. Best fit is MySQL 5.7+/Postgres, because filtering a JSON array with whereJsonContains is clean there and unsupported on SQLite — which matters for local dev and CI, and argues for a MySQL-backed test environment from day one.

Migration path. Add a nullable json column and cast it as array. Keep it nullable; do not enforce NOT NULL, because the empty-selection edge case (unchecked everything submitting null or '') is a known failure mode and a hard constraint will surface it as a 500 rather than a soft default. Backfill nothing unless the field replaces an existing column; if it does, write the migration to normalize legacy values into a consistent array shape before the field goes live, since IndexField.vue may call .join() on null and render a broken cell for pre-existing records.

Compatibility. Treat Nova compatibility as unverified until proven. The sequencing that de-risks this:

  1. Spike, don't plan. Install in a throwaway branch, render the field on one resource, save, and inspect the /nova-api request and response payloads in the network tab. This single exercise answers questions 2–4 above and costs an hour.
  2. Vendor check. Read FormField.vue for how field.value is read and what $emit('input', ...) sends. That determines the column type, the cast, and the accessor — do it before writing the migration.
  3. Write the round-trip test first. A putJson to the Nova API asserting the exact persisted array catches most failure modes including group-label leakage. Assert the array contents, not assertOk().
  4. Ship to one low-risk resource. Notification channels or tags — an attribute that is additive, non-authoritative, and easy to eyeball. Not permissions.
  5. Permissions matrix second, only if step 1–4 held. Grouped mode is effectively a permission grid, and that is the highest-consequence use case. Gate it behind a policy in fields() and validate the flattened leaf-key allow-list server-side in a FormRequest before it renders anywhere real.

The realistic long-term path is a fork. MIT license, no extension points, dormant upstream. Copying src/ and resources/js/ into nova-components/checkboxes/ and building locally is a legitimate and likely-necessary step — for Nova 5 support, for a "select all" toggle, for a max-selection limit, for a Vue 3 rebuild. Budget the fork as part of the adoption decision. If the fork isn't budgeted, the honest recommendation is to use Nova's built-ins and accept a flat, ungrouped checklist.

Alternative considered and rejected on sequencing grounds: native BooleanGroup (stores {"key": true}, renders toggle pills) or Select::make()->multiple(). Both are zero-maintenance and cover most multi-select needs. They lose only on the stacked, grouped checkbox-list affordance. If the product requirement is really "categorize these options into headings," a flat field with sorted options gets 90% of the way there.

Operational Impact

Maintenance. Effectively zero from upstream and non-zero for you. The maintainer shipped grouped checkboxes as the 1.1.0 headline in June 2022 and nothing since. Plan for the package as a vendored internal component with your name on it, not as a dependency receiving fixes. That means: pin the version, record the fork point in the repo, and assign ownership for Nova upgrades — otherwise your next Nova major becomes an unplanned scramble across every resource using this field.

Support. Community only. No SLA, no security response process, no issue triage expectation. For a form control in back-office tooling that is acceptable; it would not be for anything customer-facing or revenue-path. Note that the absence of upstream activity also means an absence of upstream regressions — the code you audit is the code you keep.

Scaling. Runtime cost is negligible — it is a form control, not a query path. The scaling concern is data-model, not throughput: every JSON-column field accumulates ad-hoc filters, search workarounds, and denormalized helper columns as reporting requirements land. Six months in, expect to own a channels_text column or a model scope to make the values queryable. If the attribute is likely to become a first-class entity (permissions, tags with metadata, anything that needs joins or counts), don't store it as JSON at all — model it relationally and use this package only as the form affordance via fillUsing/resolveUsing, or replace it with a native BelongsToMany field.

Failure modes to instrument for:

  • Vue 2/3 mismatch under Nova 4+ — field renders blank or never mounts. Detected by a smoke test on the actual Nova version, caught in the spike.
  • Silent non-persistence — renders but doesn't save. Caught by the round-trip test.
  • Empty selection — null/'' instead of [], breaking a non-nullable column or a foreach in an accessor. Guard both the fill and the resolve side; resolveUsing(fn ($v) => $v ?? []) prevents the create-form render loop from choking.
  • Group labels leaking into stored values — a naive v-model on a nested object persists 'Content' alongside 'posts.create'. Higher risk in grouped mode; caught only by asserting exact array contents.
  • Integer key stringification — 1 becomes "1"; whereJsonContains('channels', 1) won't match. Standardize on string keys everywhere.
  • Order instability — values return in DOM/click order, so equality checks and audit diffs need server-side sorting.
  • Broken index cells for legacy records — null values hitting .join(). Mitigate with displayUsing() or hideFromIndex().

Ramp-up. Low for anyone who has built a Nova field before — a few hours to be productive, a day to be confident. The flat API deliberately mirrors Select::options(), so it is learnable by analogy. The grouped API is the exception: it is the newest, least-documented, least-battle-tested surface in the package, and it is simultaneously the only reason to choose this package over free built-ins. Concentrate review effort and test coverage there, and treat the README's grouped example as a starting hypothesis rather than a specification.

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