Bootstrap Datetimepicker with AngularJS

I needed to put in a nice Date and Time selector into a form that’s using AngularJS, and wondered what might work. Searches came up with the Bootstrap Datetimepicker (on Github here) and a couple of related Stackoverflow posts, but nothing that laid it out simply. I ended up doing it mostly-but-not-quite by-the-book AngularJS, so I thought I’d write up a quick post about it in case it helps someone else.

Grab the download of the Datetimepicker from the site, and do the usual if you’re working in Rails like I am: copy the JS file into vendor/assets/javascripts, and the datetimepicker.css into vendor/assets/stylesheets, and add them to your application JS and SCSS files. From there, I made an AngularJS directive, mostly based on the one in this Stackoverflow post, though I had to make some tweaks to it. First, the HTML, which is simple enough; just put the directive into your page wherever you want the input field:

<date-time-picker recipient="recipient"></date-time-picker>

In my case, I have an ng-model called “recipient”, representing the person for whom the user is scheduling an event, so I passed in the recipient to the directive. The directive is as follows:

.directive('dateTimePicker', function() {
  return {
    restrict: 'E',
    replace: true,
    scope: {
      recipient: '='
    },
    template:
      '<div>' +
      '<input type="text" readonly data-date-format="yyyy-mm-dd hh:ii" name="recipientDateTime" data-date-time required>'+
      '</div>',
    link: function(scope, element, attrs, ngModel) {
      var input = element.find('input');

      input.datetimepicker({
        format: "mm/dd/yyyy hh:ii",
        showMeridian: true,
        autoclose: true,
        todayBtn: true,
        todayHighlight: true
      });

      element.bind('blur keyup change', function(){
        scope.recipient.datetime = input.val();
      });
    }
  }
});

The setup specifies the recipient object that’s passed in, so that the directive can set the datetime property of it. The template is straight-forward, of course, being a normal text input with the datetimepicker options — I realized while writing this that there’s not really any need to specify the format there since it’s also specified down below in the JavaScript initializer. The initializer will take precedence in this case.

The link function is the first important piece here. It finds the input field within the directive’s element, and then initializes the datetimepicker widget on it. You can specify any of the datetimepicker options here, of course. The next piece is the one that really makes things work: the bind() call. This is called when the input field is changed/blurred, and it sets the datetime property of the recipient object to the value of the input field. Essentially this works because the user will select the date and the time using the widget, then move out of the input field to submit the form. As they leave the field, this sets the recipient.datetime property, so when the form is submitted, the AngularJS object has the desired value.

A nice side-effect of the way this works is that it supports multiple datetime fields for multiple recipients. I have my recipient list in an ng-repeat block with an add button, and as additional recipients are added with different dates/times, everything works as it should. Each recipient has their own datetime field and value.

About these ads
3 comments
  1. Tjorriemorrie said:

    Here is a gist for bootstrap3: https://gist.github.com/Tjorriemorrie/6293756

    Also, I think it’s better to use ng-model (which is default for forms)
    Todo: replace the template with angular.element variable (as shown by egghead video)

  2. niargh said:

    A Plunker or jsFiddle would be awesome.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: