Recently, I was reading an article about modifying data on a response in Angular. With my previous posts dealing with TimeZones and such, it made me curious if I could also transform my data on each POST in Angular.
For example, I have many JavaScript objects with startDate and endDate properties. These dates, in JavaScript/Angualr will wind up being UTC dates. For my purposes, this isn’t very useful. I really need those dates to always be the local datetime of the user. Why you might ask? These dates are compared to other dates that are that of a specified “kind.” IE – not UTC. Philosophically, and yes I’m going on a tangent, UTC is great for keeping things all relative on the same time scale. But, when we’re looking at when something happens relative to other dates that are non-UTC/non-TimeZone specific, all we really care about is the user’s datetime in the moment.
At any rate, Angular provides nice mechanisms for manipulating/transforming data returned on response and data posted on requests. In my case, what I really wanted to do is globally change any property called startDate or endDate to a local date time. ASP.NET MVC parses JavaScript’s output from “toLocaleString” as a DateTime just fine, so this seemed like a good candidate in the transforming of my data.
To add a transform for all requests, we access the $httpProvider service and its “transformRequest” default collection of transform functions. We want to inject our own transform without affecting other transforms. The Angular docs provided a nice “appendTransform” example, so I used that as my basis. The code below adds my “transformDates” method to the transform request collection.
var appendTransform = function appendTransform(defaults, transform) { // We can't guarantee that the default transformation is an array defaults = angular.isArray(defaults) ? defaults : [defaults]; // Append the new transformation to the defaults return defaults.concat(transform); }; var transformDates = function (data) { var obj = angular.fromJson(data); for (var key in obj) { if (!obj.hasOwnProperty(key)) continue; if (key === 'startDate' || key === 'endDate') { var value = new Date(obj[key]); obj[key] = value.toLocaleString(); } } return angular.toJson(obj); }; $httpProvider.defaults.transformRequest = appendTransform($httpProvider.defaults.transformRequest, function (data) { return transformDates(data); });
Basically, on every POST/PUT, the “transformDates” methods will receive the request data from Angular. It comes in as a JSON string. The method deserializes this, and then iterates over the object’s keys to find the (2) properties I’m interested in transforming. The values are converted to a Date and then to a Local date string. Finally, the transform serializes the object back to JSON and returns it to be sent on HTTP request.
All in all, this is a nice mechanism to deal with global transformations of data without cluttering up controllers and services.