bhavin-thummar/month-picker
A Laravel/PHP package providing a month picker form component for selecting a month and year. It offers a simple way to add month-based date selection to Blade forms and application interfaces.
composer require bhavin-thummar/month-picker. Because the release history is thin (single 2022 tag), pin it explicitly (:^1.0 or whatever the current tag resolves to) so a future push doesn't silently change behavior. If the package fails to auto-discover, add BhavinThummar\MonthPicker\MonthPickerServiceProvider (verify the exact namespace in composer.json → autoload.psr-4) to config/app.php.vendor/bhavin-thummar/month-picker/README.md) for the field's exact class name and constructor, then src/ for the field class itself. That class tells you the PHP-side contract (which NovaElement it extends, what resolve() / fill() expect). Then peek at resources/js/components/*.vue to see exactly what value the picker emits — that is the single most important thing to confirm, because everything downstream (casts, validation, filters, display) depends on the stored format.Date::make('started_at') for a month/year-only picker on fields where the day is meaningless — billing month, reporting period, subscription start, contract month. Add MonthPicker::make('billing_month') to a NovaResource::fields() method, save a record, and inspect what landed in the DB column. That one round-trip tells you whether the field stores YYYY-MM, a full date, or a timestamp.YYYY-MM string, use a string(7) column (or an integer YYYYMM); if it emits a date, use date and cast it in the model. Keep the column and the picker's output format aligned — this package gives you no automatic persistence layer, so mismatches surface as silent truncation.->rules(). Nova passes rules through to the underlying request, so pair the field with explicit rules rather than trusting the widget: ->rules('required', 'date_format:Y-m') if it emits YYYY-MM, or ->rules('required', 'date') if it emits a full date. Add ->nullable() where the month is optional. ->creationRules() / ->updateRules() are useful when the month must be immutable after creation (e.g., a closing period).->default(now()->format('Y-m')) (or the format the component expects) pre-fills the current month on the create form. Use ->displayUsing(fn ($value) => $value ? Carbon::parse($value)->format('F Y') : null) so index/detail views show "April 2024" instead of a raw 2024-04 string.BelongsTo tenant/account field and a Nova filter: ->filter(new ByMonth) where the filter's apply() does a whereYear/whereMonth or a LIKE '2024-04%' depending on your column type. This lets you build "show me April's invoices" views without a full date column.protected $casts = ['billing_month' => 'date:Y-m'];) so Carbon methods work everywhere. If it emits a plain string, cast to immutable_date only if you're prepared to re-format on save — otherwise keep it a string and format at the view layer.sortable() and searchable() behavior is inherited from the parent class; the picker itself usually renders a formatted value in index. If sorting is wrong, override ->sortable() explicitly and check that the DB column sorts lexically (a YYYY-MM string column sorts correctly).laravel/nova asset pipeline) than the Nova 3 era this package was likely built against; if the compiled dist/js/field.js targets Vue 2, the component simply won't mount on Nova 4+. Test in a throwaway resource first — don't roll it into a production resource until the field renders, saves, and re-hydrates correctly.YYYY-MM, YYYY-MM-01, and a Unix timestamp. Write one record, dd() the saved value, then align migration, cast, validation, and filter to it. Do not assume; the README may not spell it out.Date in JavaScript and serializes it, a user in UTC+12 saving "March 2024" can land in February after server-side conversion. Prefer string output; if you're stuck with a date, normalize on fill() in the model or a Nova resolveUsing callback.npm run dev. Nova custom fields usually ship pre-compiled assets, but if you need to modify the component, you'll have to npm install && npm run prod in the package folder and republish. Check the package's package.json for a pinned Vue version — a Vue 2 dependency will fight your Nova 4 host. Also check nova.mix.js/webpack.mix.js presence; older packages sometimes have none, making rebuilds painful.resolveUsing, fillUsing, displayUsing, and default to be your only hooks. If you need a range (start month → end month), you'll build two fields and validate cross-field with ->rules() referencing the other attribute; don't expect the package to handle ranges.php artisan nova:publish run, (3) browser console for Vue mount errors, (4) Nova::script/Nova::style loading the package dist, (5) value format mismatch between resolve() and the component's prop. Nine times out of ten it's (5) or a Vue version mismatch.php artisan nova:field acme/month scaffolds it) or a Select field populated with now()->subMonths(12)->monthsUntil(now()). A month picker is roughly 40 lines of Vue and a stub field class — for a package this small the in-house route is often lower risk than adopting an unmaintained dependency.How can I help you explore Laravel packages today?