The user aims to incorporate datetimepicker.js, a jQuery plugin, into an AngularJS application by developing a custom directive. The primary obstacle is that the datetimepicker does not seamlessly bind to AngularJS’s ng-model, which disrupts the two-way data binding mechanism. As a result, there are inconsistencies between the Angular model and the date chosen through the datetimepicker.
Here in example we have Eonasdan/bootstrap-datetimepicker
The Eonasdan/bootstrap-datetimepicker library is a jQuery-based datetime picker and does not natively support Angular. To integrate it with Angular, you would need to use a wrapper or directive that bridges the gap between jQuery and Angular.
So here we have given solution for all angular versions
app.directive('datetimepicker', function() { return { restrict: 'A', require: 'ngModel', link: function(scope, element, attrs, ngModelCtrl) { console.log('call datetimepicker link...'); var picker = element.datetimepicker({ dateFormat: 'dd/MM/yyyy hh:mm:ss', useCurrent: false // Prevent default date setting on initialization }); // Model -> View (render) ngModelCtrl.$render = function() { console.log('ngModelCtrl.$viewValue@' + ngModelCtrl.$viewValue); picker.setDate(ngModelCtrl.$viewValue || ''); }; // View -> Model (change event) picker.on('dp.change', function(e) { console.log('dp.change ' + e.date); scope.$apply(function(){ // Store Date object in the model ngModelCtrl.$setViewValue(e.date ? e.date.toISOString() : null); // Using ISO string format }); }); // Optional: Clear date when modal is opened again scope.$on('modalOpened', function() { ngModelCtrl.$setViewValue(null); // Reset the date on modal open picker.clear(); }); // Optional: Listen for modal closing event and clear date if needed scope.$on('modalClosed', function() { picker.clear(); }); } }; });
Controller app.controller('MainCtrl', [ '$scope', function ($scope) { $scope.dueDate = new Date(); }, ]);Datetime Picker Example
For Angular 2+ versions , need to install packages using below command
npm install jquery moment eonasdan-bootstrap-datetimepicker
Need to add styles and scripts in angular.json file
"styles": [ "node_modules/bootstrap/dist/css/bootstrap.min.css", "node_modules/eonasdan-bootstrap-datetimepicker/build/css/bootstrap-datetimepicker.min.css" ], "scripts": [ "node_modules/jquery/dist/jquery.min.js", "node_modules/moment/min/moment.min.js", "node_modules/eonasdan-bootstrap-datetimepicker/build/js/bootstrap-datetimepicker.min.js" ]
datetime-picker.directive.ts
import $ from 'jquery'; import { Directive, ElementRef, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core'; import 'eonasdan-bootstrap-datetimepicker'; @Directive({ selector: '[appDatetimepicker]', standalone: true }) export class DatetimepickerDirective implements OnInit, OnDestroy { @Input() options: any; @Output() dateChange = new EventEmitter(); private picker: any; constructor(private el: ElementRef) {} ngOnInit(): void { // Use type assertion to avoid TypeScript error this.picker = ( $(this.el.nativeElement)).datetimepicker(this.options); this.picker.on('dp.change', (e: any) => { this.dateChange.emit(e.date ? e.date.format('YYYY-MM-DD HH:mm') : ''); }); } ngOnDestroy(): void { if (this.picker) { ( this.picker.data('DateTimePicker')).destroy(); } } }
App.component.html
app.component.ts
import { Component } from '@angular/core'; import { DatetimepickerDirective } from './datetime-picker/datetime-picker.directive'; @Component({ selector: 'app-root', templateUrl: './app.component.html', standalone : true, imports: [DatetimepickerDirective], }) export class AppComponent { datetimeOptions = { format: 'YYYY-MM-DD HH:mm', sideBySide: true, showTodayButton: true }; onDateChange(date: string): void { console.log('Selected date:', date); } }
No Standalone Components: Angular 2 to 17 doesn’t support the standalone: true flag in components or directives, so the directive needs to be declared in the module.
Module-based Declaration: The directive will be declared within an Angular module (@NgModule) instead of being standalone.
datetime-picker.directive.ts
import * as $ from 'jquery'; import { Directive, ElementRef, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core'; import 'eonasdan-bootstrap-datetimepicker'; @Directive({ selector: '[appDatetimepicker]' }) export class DatetimepickerDirective implements OnInit, OnDestroy { @Input() options: any; @Output() dateChange = new EventEmitter(); private picker: any; constructor(private el: ElementRef) {} ngOnInit(): void { this.picker = $(this.el.nativeElement).datetimepicker(this.options); this.picker.on('dp.change', (e: any) => { this.dateChange.emit(e.date ? e.date.format('YYYY-MM-DD HH:mm') : ''); }); } ngOnDestroy(): void { if (this.picker) { this.picker.data('DateTimePicker').destroy(); } } }
Now need to import DatetimepickerDirective in the app module’s import array. Other than this everything is the same as angular 18.
In summary, while Eonasdan/bootstrap-datetimepicker itself is not natively compatible with Angular, there are Angular-specific wrappers and alternative libraries available that can provide similar functionality.