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 Boolean Datetime Field Laravel Package

pragmarx/nova-boolean-datetime-field

pragmarx/nova-boolean-datetime-field is a Laravel Nova field that pairs a boolean toggle with a date/time input, letting you enable or disable a timestamp from one control. Useful for publish-at, expiry, and scheduled on/off settings in Nova resources.

View on GitHub
Deep Wiki
Context7

Getting Started

Install into a project that already has Laravel Nova running (this field is useless without Nova — it is a Vue component plus a thin Field subclass, not a standalone form widget):

composer require pragmarx/nova-boolean-datetime-field

There is no service provider to register and no migration shipped — it is a pure field package. Publish assets only if the README tells you to (php artisan nova:publish), which is normally only needed when the compiled dist/js bundle is missing for your Nova major version.

Look at these two files first, in this order:

  1. src/ — the single field class. Read resolve()/fill()/fillUsing() if present; that is where the boolean↔null semantics live and is the only part of the package that can surprise you.
  2. dist/js/field.js (or resources/js/) — confirms which Nova version the bundle was built against. A 21-star Nova field is usually pinned to the Nova major version that existed when it was last tagged; check the last commit date against your laravel/nova version before building a workflow on it.

The canonical first use case is a single nullable timestamp column that doubles as a state flag:

// migration
$table->timestamp('published_at')->nullable();
// app/Nova/Post.php
use PragmaRX\...\BooleanDatetime; // confirm FQCN from composer.json autoload / src/

BooleanDatetime::make('Published At')
    ->rules('nullable', 'date'),
// app/Models/Post.php
protected $casts = ['published_at' => 'datetime'];

Toggle off ⇒ column stores null (unpublished). Toggle on ⇒ the datetime picker is revealed and the chosen value is stored. This gives you one column and one UI control instead of a redundant is_published boolean that can drift out of sync with the timestamp.

Implementation Patterns

Treat the field as a nullable-datetime field with a nicer affordance. Everywhere else in the app keep writing normal Laravel:

Post::whereNotNull('published_at')->where('published_at', '<=', now())->get();
$post->published_at = null;   // "unpublish" without touching any boolean column

Two-column variant (separate is_published boolean). If you already have a boolean column, don't fight the field — bridge it with fillUsing(), which is the package's most useful extension point:

BooleanDatetime::make('Published At')
    ->fillUsing(function ($request, $model, $attribute) {
        $value = $request->input($attribute);
        $model->{$attribute}        = $value ?: null;
        $model->is_published        = (bool) $value;
    })

Form-only vs index-only. The interactive toggle is only meaningful on forms; on index/detail it degenerates to a timestamp cell. Keep the resource clean:

BooleanDatetime::make('Published At')
    ->onlyOnForms()
    ->rules('nullable', 'date'),

DateTime::make('Published At')
    ->onlyOnIndex()
    ->displayUsing(fn ($value) => $value ? $value->diffForHumans() : '—'),

Scheduling / expiry patterns. This field shines for "active until", "trial ends at", "muted until" — states where the absence of a timestamp is the state. Anywhere you'd otherwise write is_active + active_until and keep them consistent in three places, collapse to one column.

Compose with Nova's conditional UI. Pair it with ->dependsOn() on neighbouring fields so the datetime picker doesn't clutter a dense form, and put the toggle in a Panel/Tab alongside related lifecycle fields rather than mixed into timestamps like created_at.

Keep a read model in sync. If you index or filter heavily on publication state, add a published_at IS NOT NULL scope on the model and a generated/derived index column rather than querying whereNotNull on a large table.

Gotchas and Tips

  • Timezone conversion is the number one source of "the toggle lies". Nova converts datetimes per Nova::$useBrowserTimezone (and config('app.timezone') otherwise). Nulls are safe, but a value saved from a browser-timezone user comes back shifted in a different user's session. Decide once, set Nova::useBrowserTimezone() explicitly, and never mix it with manual ->withTimezone() fiddling.
  • The column must be nullable, and the cast must be datetime, not boolean. A boolean cast on a timestamp column silently turns every date into 1.
  • Empty-string submissions. Nova forms can post '' rather than omitting the key; nullable|date rejects ''. If you hit validation errors when toggling off, normalise in the field's fillUsing() or use prepareRules() to strip the rule when the toggle is off.
  • ->sortable() on a nullable timestamp sorts differently across engines — MySQL puts NULL first ascending, Postgres puts it last. If the index card is the primary triage view, sort on a non-null derived column instead.
  • Nova major-version lock-in. Nova 4+ requires the field's JS to register via Nova.booting in a published resources/js/field.js; Nova 3 used Nova::script()/style(). If the toggle renders but the datetime input never appears, the asset bundle was built for the other major version — rebuild the component locally rather than debugging your resource.
  • Don't declare it twice. Adding both the BooleanDatetime field and a plain DateTime field bound to the same attribute on the same form means two components write the same key and the last one in the payload wins, nondeterministically.
  • Debugging "it saved the wrong thing": dump $request->all() in fillUsing() before touching the package. Nine out of ten reports against single-field Nova packages are a $fillable/$guarded omission on the model or a request key mismatch (published_at vs publishedAt normalization in older Nova releases).
  • With only 21 stars and no dependents, budget for maintenance. Vendor the field class into app/Nova/Fields/ if you're shipping long-lived software: it is ~50 lines of PHP and a small Vue SFC, and that removes the risk of a Nova upgrade leaving you stranded on the last compatible tag. The extension points you'd need (resolve, fill, fillUsing, displayUsing) are all standard Laravel\Nova\Fields\Field API, not package-specific.
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.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin