6

Given a WebApi2 service that returns json values like this:

{
    id: 1109,
    effectiveDate: "2014-10-05T00:00:00", // the date is a string (newtonsoft.json)
    text: "Duis et rhoncus nibh. Cras rhoncus cursus diam",
    fundSource: "Test"
}

I need the date to appear in the bound angular / bootstrap / date picker correctly.

I need to transform the date into the format yyyy-mm-dd (without the time) when binding it to an input box. Just a pointer to some documentation explaining what the correct way to serialize dates from the API to angular. I am sure that effectiveDate should actually be a Date object and not a string.

<input class="form-control" 
       type="text" 
       name="effectiveDate" 
       ng-model="consultation.effectiveDate" 
       data-date-picker="yyyy-mm-dd" 
       placeholder="Date" />

For completness, the service returning the json values looks like this:

app.factory('Service', ['$http', '$location', '$interpolate', function ($http, $location, $interpolate) {
    return {
        get: function (account) {
            var url = 'api/consultations/{account}';
            return $http
                .get(Api.format(url, { account: account }))
                .then(function (response) { return response.data; });
        }
    };
}]);

The controller method calls it like this:

service.get($scope.urlData.account).then(function(consultations) {
    $scope.consultations = consultations;
});
1
  • Convert the date in string format to JavaScript Date object. And the rest should work fine. You can use normal JavaScript for Date-Time handling in JavaScript but it's better to use some library that handles cross browser compatibility. You may try moment.js. Your scope variable effectiveDate should contain the Date object. Commented Oct 8, 2014 at 4:36

3 Answers 3

3

I ran into the exact same problem and eventually solved it by writing an Angular http interceptor. It parses the server's response and converts all Datetime strings with ISO/UTC format into actual JavaScript date objects. This allows direct binding to the datepicker and solves validation issues.

Here's the client-side Angular code, consisting of a factory (the interceptor) and the config part for providing the http interceptor:

angular.module("app")
    .factory('dateInterceptor', function () {
        var regexIsoUtc = /^(\d{4}|\+\d{6})(?:-(\d{2}))(?:-(\d{2}))(?:T(\d{2})):(\d{2}):(\d{2})Z$/;

        function matchDate(dateString) {
            if (dateString.length === 20) {
                return dateString.match(regexIsoUtc);
            }
            return false;
        };

        function convertDateStringsToDates(object) {
            // ensure that we're processing an object
            if (typeof object !== "object") {
                return object;
            }

            for (var key in object) {
                if (!object.hasOwnProperty(key)) {
                    continue;
                }
                var value = object[key];

                // check for string properties with a date format
                if (typeof value === "string" && matchDate(value)) {
                    var date = new Date(value); // create the date from the date string
                    object[key] = date; // we're mutating the response directly
                } else if (typeof value === "object") {
                    convertDateStringsToDates(value); // recurse into object
                }
            }
            return null;
        }

        var interceptor = {
            'response': function (response) {
                if (response.data) {
                    convertDateStringsToDates(response.data);
                }
                return response;
            }
        };
        return interceptor;
    })

    .config(["$httpProvider", function ($httpProvider) {
        $httpProvider.interceptors.push('dateInterceptor'); // intercept responses and convert date strings into real dates
    }]);

On the server side I configured Newtonsoft.Json to serialize dates using the ISO format with UTC time zone, which is the format I test against in the interceptor:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services
        var formatters = GlobalConfiguration.Configuration.Formatters;
        var jsonFormatter = formatters.JsonFormatter;
        var settings = jsonFormatter.SerializerSettings;

        // serialize dates into ISO format with UTC timezone
        settings.DateFormatHandling = DateFormatHandling.IsoDateFormat;
        settings.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
        settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
    }
}

The interceptor is thankfully based on the code from Automatic JSON date parsing with AngularJS and AngularJS HTTP Date Interceptor Factory.

Sign up to request clarification or add additional context in comments.

Comments

2

Use angular filter module Date filter in angularjs

{{ effectiveDate | date:'yyyy-MM-dd' }}

Comments

1

If you want to use bootstrap components in angular then you have to create a directive or you can reuse some existing like http://angular-ui.github.io/bootstrap/#/datepicker

Example how to use bootstrap date picker with angular:

 <body ng-app="app" >

    <div class="form-horizontal" ng-controller="ctrl">
        <input type="text" datepicker-popup="MM/dd/yyyy" ng-model="consultation.effectiveDate" datepicker-options="dateOptions" date-disabled="" ng-required="true" />
    </div>
 </body>

js:

app.controller('ctrl', function ($scope, $timeout) {

 $scope.consultation = {
    id: 1109,
    effectiveDate: "2014-10-05T00:00:00", // the date is a string (newtonsoft.json)
    text: "Duis et rhoncus nibh. Cras rhoncus cursus diam",
    fundSource: "Test"
  };

  $scope.dateOptions = {
    'starting-day': 1
  };
});

http://plnkr.co/edit/veOWWlBrKdL5CaMJf61h?p=preview

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.