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.
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:
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.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.
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.
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.datetime, not boolean. A boolean cast on a timestamp column silently turns every date into 1.'' 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.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.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.$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).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.How can I help you explore Laravel packages today?