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.
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:
data-* attributes, and the format contract, then reproduce that in Blade + a small JS initializer.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:
<input type="text"> with data-format, data-locale, data-side-by-side, etc., initialized by a JS plugin on DOMContentLoaded.DateTime unless a transformer is configured.<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.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:
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"
/>
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,
});
});
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:
Y-m-d H:i:s) and make it the only thing the server accepts. Document it next to the component.->timezone($user->timezone)), and set config('app.timezone') = 'UTC'.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.<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.
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.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.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.DateTime object. In your Laravel port, the Form Request normalization step above is that transformer — don't skip it.date_format on the server is mandatory, not decorative.old() must feed the value attribute in the exact format the picker expects, or the field re-renders blank/empty after a failed submit.data-* attributes (as in the snippet above).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.FormRequest rule set. In both cases, the abstraction boundary is what makes replacement cheap.$(...).datetimepicker is not a function.resources/js with a comment naming the upstream version — you now own the upgrade path.How can I help you explore Laravel packages today?