rsobon rsobon - 11 months ago 300
JSON Question

Parse date string to Date object when loading Angular UI Bootstrap Datepicker

I'm using Angular UI Bootstrap Datepicker:

When I render form using data received from the server, there is problem with datetime fields. My input datepicker looks like this:

<form name="itemForm">
<input type="datetime" class="form-control" id="startedAt" name="startedAt"
ng-click="open($event, 'startedAt')"

My server returns response datetime as JSON string:

startedAt: "2015-05-29T02:00:00+0200"

When I assign response data to the model
$scope.item = response;
, datepicker input field is rendered correctly (correct date is selected and it's properly formatted in format I selected). The problem is that validation does not pass. I get:

itemForm.startedAt.$invalid == true

I noticed that data bound to the datepicker field should be
object and not string (when I select new date from the datepicker,
is a

I managed to work around this issue and do this in the controller:

$scope.item = response;
$scope.item.startedAt = new Date($scope.item.startedAt);

It works this way... But I wouldn't like to manually convert string do date every time I get a response from the server. I tried to create a directive, that I can assign to the datepicker input field so it converts the
for me:

.directive("asDate", function () {
return {
require: 'ngModel',
link: function (scope, element, attrs, modelCtrl) {

modelCtrl.$formatters.push(function (input) {

var transformedInput = new Date(input);

if (transformedInput != input) {

return transformedInput;

Well it works, because now I can see
object, when I output model in my view:
. However still validation fails! I suspect this is some problem with me understanding how data flows between model and the view, and how UI Bootstrap hooks into it.

Also when I change my directive from
, validation works OK, but datepicker does not format my datetime (insted of nicely formattet
I see ISO string inside the input)


As this is intentional behaviour of angular-ui-bootstrap datepicker (, I ended up using Angular service/factory and moment library.

Service dateConverter can be injected globally to intercept all HTTP requestes/responses or only in desired controllers.

Here I use Restangular library to handle request to REST API, hence the response.plain() method which takes only object properties, and not Restangular methods/properties.

var Services = angular.module('app.Services', []);

    .factory('dateConverter', ['dateFilter', function (dateFilter) {

        var dateConverter = {};

        dateConverter.prepareResponse = function (response) {
            for(prop in response.plain()) {
                if (response.hasOwnProperty(prop)) {
                    if(moment(response[prop], moment.ISO_8601, true).isValid()) {
                        response[prop] = new Date(response[prop]);
            return response;

        dateConverter.prepareRequest = function (item) {
            for(prop in item.plain()) {
                if (item.hasOwnProperty(prop)) {
                         item[prop] = dateFilter(item[prop] , "yyyy-MM-ddTHH:mm:ssZ")
            return item;

        return dateConverter;