Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

binding a date in angularjs using webapi and the bootstrap date picker

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;
});
like image 937
Jim Avatar asked Oct 08 '14 04:10

Jim


2 Answers

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.

like image 57
Mobiletainment Avatar answered Nov 13 '22 19:11

Mobiletainment


Use angular filter module Date filter in angularjs

{{ effectiveDate | date:'yyyy-MM-dd' }}
like image 2
Geo Jacob Avatar answered Nov 13 '22 19:11

Geo Jacob