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

mablae/datetimepicker-bundle

mablae/datetimepicker-bundle is a Symfony bundle that simplifies adding a JavaScript date and time picker to your forms. It provides reusable form types and asset integration for quick, minimal-configuration datetime selection in templates.

View on GitHub
Deep Wiki
Context7

Getting Started

Reality check before you composer require: mablae/datetimepicker-bundle is a Symfony bundle, not a Laravel package. There is no ServiceProvider, no config/datetimepicker.php, no Facade, and no published migrations or assets command. It wraps the Bootstrap 3 / Eonasdan bootstrap-datetimepicker JavaScript widget in a Symfony Form Type and registers it through the Symfony DI container. In a Laravel app you cannot consume it as-is. Your real options are:

  1. Treat it as a reference implementation — read how it wires the input, the data-* attributes, and the format contract, then reproduce that in Blade + a small JS initializer.
  2. Port the pattern — a Blade component, a Vite entry point, and a Form Request that normalizes/validates the submitted string.

Anything involving symfony/form, Twig form themes, and the Symfony container inside Laravel is more work than the port itself.

Where to look first in the repo:

  • Form/Type/*.php — the actual form type class and its option bag (format, locale, widget, picker_options). This is the contract you're copying.
  • DependencyInjection/ and Resources/config/ — how the type is registered as a service (interesting only if you're on Symfony).
  • Resources/views/Form/ — the Twig form theme block that renders the input and emits data-* attributes.
  • Resources/public/ — the JS/CSS assets the bundle expects you to publish or include.
  • README.md — the form type service name and the minimum YAML/PHP config to enable it.

Minimal evaluation path for a Laravel developer:

  1. Do not install it in a production Laravel app. Spin up a throwaway Symfony 2/3 skeleton (this bundle predates Symfony Flex) or just read the form type and Twig block directly — it's small.
  2. Identify the two things worth stealing:
    • The widget contract: an <input type="text"> with data-format, data-locale, data-side-by-side, etc., initialized by a JS plugin on DOMContentLoaded.
    • The server-side contract: one submitted string that must be parsed with an explicit, known format — the bundle does not hand you a DateTime unless a transformer is configured.
  3. First real use case in Laravel: replace a raw <input type="datetime-local"> on an admin form with a Bootstrap-styled popup, submit an ISO-8601 string, and validate with 'starts_at' => ['required', 'date_format:Y-m-d H:i:s']. The bundle's value to you is showing the input/JS/PHP boundary, not giving you integration.

Implementation Patterns

What the bundle does in Symfony (the pattern to copy):

// Symfony form usage
$builder->add('startsAt', DateTimePickerType::class, [
    'format' => 'YYYY-MM-DD HH:mm',
    'picker_options' => [
        'locale' => 'de',
        'sideBySide' => true,
    ],
]);

The form type renders a text input; the Twig theme emits the data-* attributes the JS plugin reads at page load. The submitted value is a string — persistence and timezone handling are your problem, not the bundle's.

Laravel translation of that pattern:

  • Blade component (resources/views/components/datetime-picker.blade.php):
@props(['name', 'value' => null, 'format' => 'Y-m-d H:i:s', 'locale' => 'en'])

<input
    type="text"
    name="{{ $name }}"
    id="{{ $name }}"
    value="{{ old($name, $value?->format($format)) }}"
    data-datetimepicker
    data-format="{{ $format }}"
    data-locale="{{ $locale }}"
    {{ $attributes->merge(['class' => 'form-control']) }}
    autocomplete="off"
/>
  • JS initialization (Vite/Mix entry point, not Symfony's asset conventions):
import moment from 'moment';
import 'moment/locale/de';
import 'eonasdan-bootstrap-datetimepicker';

document.querySelectorAll('[data-datetimepicker]').forEach((el) => {
    window.moment.locale(el.dataset.locale || 'en');
    $(el).datetimepicker({
        format: el.dataset.format,
        sideBySide: true,
    });
});
  • Request normalization + validation — the important part, and the part the bundle leaves to you:
protected function prepareForValidation(): void
{
    if ($this->filled('starts_at')) {
        $this->merge([
            'starts_at' => Carbon::createFromFormat(
                'Y-m-d H:i:s',
                $this->input('starts_at')
            )?->toDateTimeString(),
        ]);
    }
}

public function rules(): array
{
    return [
        'starts_at' => ['required', 'date_format:Y-m-d H:i:s'],
    ];
}

Day-to-day workflow regardless of whether you ported it or (on Symfony) use it directly:

  1. Pick one canonical wire format (ISO-8601 or Y-m-d H:i:s) and make it the only thing the server accepts. Document it next to the component.
  2. Store UTC, render in the user's timezone (->timezone($user->timezone)), and set config('app.timezone') = 'UTC'.
  3. Populate from old() first, then the model value — hand-rolled pickers break most often after a validation redirect when the user's typed string gets clobbered by a reformatted model value.
  4. Keep picker options in one place — a Blade component prop bag or a small config file — not scattered across views.
  5. Isolate behind your own type/component (<x-datetime-picker>), so swapping to Flatpickr, Pikaday, or a Livewire/Alpine component later is a one-file change.

On Symfony (the only place this is directly usable), the pattern is: register the form type once as a service (the bundle does this for you), reference it in forms via ->add('field', DateTimePickerType::class, [...]), include the bundle's Twig form theme, and ensure the JS/CSS assets are published and loaded. Wrap it in your own App\Form\Type\DateTimePickerType that composes the bundle's type with house defaults so templates and forms never reference the vendor class directly.

Gotchas and Tips

  • Abandonment is the headline risk. 1 star, 0 dependents, and a Symfony 2-era directory structure mean no PHP 8.2 / Symfony 6 compatibility guarantees, no security patching, and no upstream fixes when the underlying picker breaks. Treat it as a historical reference for the pattern, not a long-lived dependency.
  • Bootstrap 3 + jQuery + Moment.js. The Eonasdan bootstrap-datetimepicker it wraps expects Bootstrap 3 markup and Moment. It will not look or behave correctly in a Bootstrap 5 or Tailwind front end without meaningful CSS work, and it drags jQuery into your Vite bundle. If your app is jQuery-free, porting the pattern and using a modern picker is the cheaper path.
  • Asset pipeline mismatch. The bundle assumes Symfony's templating/asset conventions. Laravel's Vite or Mix pipeline will not discover Resources/public automatically — copy the JS/CSS into resources/js and resources/css if you're borrowing the look, and import it explicitly from your entry point.
  • Format strings are not portable. The JS side uses Moment.js tokens (YYYY-MM-DD HH:mm), while Laravel/PHP validation and Carbon::createFromFormat use PHP date tokens (Y-m-d H:i:s). They look similar and silently disagree on mm (minutes vs. month) and DD/dd. Keep two constants and never pass one to the other.
  • The submitted value is a string, not a DateTime. On Symfony you need a data transformer to get a DateTime object. In your Laravel port, the Form Request normalization step above is that transformer — don't skip it.
  • Client-side format ≠ server-side accepted format. The picker constrains what the browser sends; a crafted request can send anything. date_format on the server is mandatory, not decorative.
  • Validation redirects wipe the widget. old() must feed the value attribute in the exact format the picker expects, or the field re-renders blank/empty after a failed submit.
  • CSP and inline init. The bundle's Twig block may initialize the picker with inline scripts. If you enforce Content-Security-Policy, either use a nonce or move initialization into your compiled JS entry point reading data-* attributes (as in the snippet above).
  • Locale and timezone mismatch. data-locale="de" changes the display language/format, not the timezone. Users in Europe/Berlin will submit a local wall-clock time; convert explicitly before persisting.
  • Extension points worth knowing: on Symfony, subclass the bundle's form type to set house defaults; on Laravel, the equivalent is a Blade component prop bag plus a FormRequest rule set. In both cases, the abstraction boundary is what makes replacement cheap.
  • Debugging checklist when the picker "does nothing": confirm jQuery and Moment are loaded before the picker plugin, confirm the plugin is attached after the element exists (not before it's in the DOM), confirm Bootstrap's CSS is present (the popup renders but is invisible without it), and check the browser console for $(...).datetimepicker is not a function.
  • Pin nothing, own everything. If for some reason you do vendor the JS assets, copy them into resources/js with a comment naming the upstream version — you now own the upgrade path.
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.
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
uni-method/symfony-lib