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

Datetimepicker Bundle Laravel Package

mwsimple/datetimepicker-bundle

MWSImple DateTimePickerBundle is a Symfony bundle that adds date and time picker support to forms, making it easier to render and handle date/time inputs in web applications with minimal configuration.

View on GitHub
Deep Wiki
Context7

Getting Started

Read this first: the package is not a Laravel package. mwsimple/datetimepicker-bundle is a Symfony bundle (Resources/config/services.xml, Form/Type/*, Resources/views/Form/*) that registers a form type wrapping the Eonasdan/Bootstrap-DateTimePicker widget. On a Laravel codebase you have two realistic options, and you should decide before writing any code:

  1. Adopt only the front-end asset (recommended). Copy the JS/CSS out of Resources/public/ into public/vendor/datetimepicker/, and re-implement the ~40 lines of the bundle's form type as a Blade component. This gets you the identical UI with zero Symfony runtime.
  2. Install the bundle with composer require mwsimple/datetimepicker-bundle. This only works if it drags in symfony/framework-bundle and the bundle's own dependency constraints still allow your PHP version — check composer.json before running it. Pulling a Symfony framework into a Laravel app to render a date input is almost never worth it.

Where to look, in order:

  • Resources/views/Form/ — the Twig block that renders the input-group markup. This is what you port to Blade.
  • Form/Type/ — the class that calls $builder->add('field', DatetimepickerType::class, ['format' => ...]). It shows which options the bundle exposes and which it hardcodes.
  • Resources/public/ — the picker JS/CSS (and any bundled moment.js build).
  • DependencyInjection/ — any configurable defaults worth mirroring in a Laravel config file.

First use case: an appointment/event scheduling field on an admin form. Minimal Laravel version:

{{-- resources/views/components/datetimepicker.blade.php --}}
@props(['name', 'value' => null, 'id' => null])
@php $id ??= 'dtp-'.\Illuminate\Support\Str::random(8); @endphp
<div class="input-group date" id="{{ $id }}" data-target-input="nearest">
    <input type="text" name="{{ $name }}" id="{{ $id }}-input"
           class="form-control" value="{{ old($name, $value) }}" autocomplete="off">
    <div class="input-group-append" data-target="#{{ $id }}" data-toggle="datetimepicker">
        <span class="input-group-text"><i class="far fa-calendar"></i></span>
    </div>
</div>
@push('scripts')
<script>
$(function () {
    $('#{{ $id }}').datetimepicker({ format: 'YYYY-MM-DD HH:mm:ss', locale: '{{ app()->getLocale() }}' });
});
</script>
@endpush

Implementation Patterns

Single source of truth for the format. The most common bug in this integration is a mismatch between the JS format string (YYYY-MM-DD HH:mm:ss, moment tokens) and the PHP validation/serialization format (Y-m-d H:i:s, Carbon tokens). Define both in one config entry so they can never drift:

// config/datetimepicker.php
return [
    'js_format'   => 'YYYY-MM-DD HH:mm:ss',
    'php_format'  => 'Y-m-d H:i:s',
    'locale'      => env('APP_LOCALE', 'en'),
    'side_by_side' => true,
];

Emit js_format into the component, use php_format in Rule::date()->format(...) and in Carbon::createFromFormat() on save.

Blade component + validation rule as a pair. Treat the component and a matching DateTimeInput rule (or a prepareForValidation() hook) as one unit. Because the widget posts a string, normalize in the FormRequest:

protected function prepareForValidation(): void
{
    if (blank($this->input('starts_at'))) {
        $this->merge(['starts_at' => null]);
    }
}

Livewire. Wrap the picker in wire:ignore and re-init after DOM morphs; otherwise Livewire replaces the input node and the picker silently stops opening:

<div wire:ignore>
    <x-datetimepicker name="starts_at" :value="$starts_at" />
</div>

If you need the value back into Livewire, add an onchange that dispatches: $('#id-input').on('change.datetimepicker', e => @this.set('starts_at', e.target.value)).

Multiple pickers / dynamic rows. Never hardcode the initializer to one selector. The component generates a unique ID (as above) and pushes per-instance JS. For dynamically added rows, re-run the initializer inside the "row added" callback and guard with if (!$('#id').data('DateTimePicker')).

Where the Symfony bundle actually helps you (if you run it under Symfony). Use the bundle's form type directly with $builder->add('starts_at', DatetimepickerType::class) and set defaults through the bundle config in config/packages/; you get the widget wired to Symfony's form theme. Don't mix that with hand-rolled jQuery init on the same field — double initialization produces two overlapping calendars.

Asset pipeline. If you use Vite, import the picker CSS/JS in resources/js/app.js rather than <script> tags, and import moment with only the locales you need (import 'moment/locale/fr') to keep the bundle small. Import order matters: moment → bootstrap-datetimepicker.

Gotchas and Tips

  • Upstream is effectively abandoned. The Eonasdan picker is Bootstrap 3-era and depends on moment.js (v2), not dayjs/Luxon. It has known layout conflicts with Bootstrap 4/5 (positioning, missing Glyphicons) — expect CSS surgery if your app is BS4+. For new builds on Bootstrap 5, tempusdominus-bootstrap-5 (same API lineage) is a cleaner drop-in and lets you keep your Blade component unchanged.
  • Composer constraints will likely block installation. PHP and symfony/framework-bundle version pins from the Symfony 2/3 era often conflict with a modern Laravel/Symfony stack. Run composer require --dry-run first and read the solver output before touching composer.json.
  • Missing moment locale = silent English-only. The picker never errors when a locale file is absent; it falls back. Verify in the network tab that moment/locale/{locale}.js actually 200s, and call moment.locale(...) before initializing.
  • Timezone drift. The widget gives you a naive local string. Parse it in the app timezone and store UTC: Carbon::createFromFormat(config('datetimepicker.php_format'), $value, config('app.timezone'))->utc(). Do not let strtotime()/implicit parsing guess.
  • Clearing the field yields '', not null. SQL will happily store an empty string into a datetime column on permissive drivers, or throw on strict ones. Normalize in prepareForValidation() (see above) and make the column nullable.
  • Re-initialization leaks widgets. Calling .datetimepicker({...}) twice on the same element stacks handlers and produces flicker or duplicated popups. Guard with if ($el.data('DateTimePicker')) { $el.data('DateTimePicker').destroy(); } before re-init — essential when options change (e.g. switching a "side-by-side" toggle).
  • Debugging hooks. $('#id').data('DateTimePicker') exposes the live instance (date(), format(), options()); $('#id').on('error.datetimepicker', ...) catches malformed input silently rejected by the picker. If the calendar opens in the wrong place, it's almost always a position: relative ancestor or a overflow: hidden modal — use widgetPositioning: { vertical: 'bottom' }.
  • Extension points worth preserving from the bundle: the format, language/locale, sideBySide, minDate/maxDate, and daysOfWeekDisabled options. Surface these as component props so call sites don't reach into raw JS, and forward only the non-null ones into the datetimepicker({...}) call.
  • Don't render the picker inside a hidden tab/modal without a fix. It computes size on init and will render at zero width; initialize on shown.bs.tab / shown.bs.modal instead of DOMContentLoaded.
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.
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment