<!DOCTYPE html>
<html ng-app="myApp">
<head>
<script src="https://code.angularjs.org/1.3.0-beta.5/angular.js" data-semver="1.3.0-beta.5" data-require="angular.js@*"></script>
<script data-require="angular-resource@*" data-semver="1.2.14" src="http://code.angularjs.org/1.2.14/angular-resource.js"></script>
<link href="style.css" rel="stylesheet" />
<script src="script.js"></script>
</head>
<body ng-controller="MyCtrl">
<h1>Car is</h1>
<p>{{ car.toString() }}</p>
</body>
</html>
angular.module("myApp", ['controllers', 'services']);
// ---------------------------- controller -------------------------------------
angular.module('controllers', [])
.controller('MyCtrl', function($scope, HttpCarService) {
var successCallback = function(data, status, headers, config) {
$scope.car = data;
};
var errorCallback = function(data, status, headers, config) {
$scope.data = "there was an error";
};
HttpCarService.getCar().then(successCallback, errorCallback);
});
// ------------------------------ service --------------------------------------
angular.module('services', ['ngResource'])
.factory('HttpCarService', function($resource, $q) {
var resource = $resource('car.json'); // in real life this would be a URL
return {
/**
* This method will return an instance of Car (that is, this will deserialize
* the returned JSON into a Car object).
*/
getCar: function(config) {
var deferred = $q.defer();
var car = null;
var deserializeResponse = function(data, status, headers, config) {
var c = angular.fromJson(data);
car = new Car(c);
deferred.resolve(car);
};
var errorCallback = function(data, status, headers, config) {
deferred.reject("something wrong");
};
var result = resource.get(
// if your resource needs url params, pass them to the getCar function
// with a config object, and then define them here. e.g.
// {carId: config.carId}
{},
deserializeResponse,
errorCallback);
return deferred.promise;
}
};
});
// ----------------------------- domain layer ----------------------------------
function Car(car) {
this.make = car.make;
this.model = car.model;
this.year = car.year;
this.torque = car.torque;
}
Car.prototype.toString = function() {
return this.year + " " + this.make + " " +
this.model + " with " + this.torque + " torque";
};
How to Deserialize Responses in AngularJS
=========================================
If you have a class called "Car" and you make a request to a "CarService", chances
are you want the response to be deserialized into a Car instance as soon as possible.
One option is to use the $http `transformResponse` option, which lets you provide a function
that mutates responses. There are a few problems with that:
- The `transformResponse` for $resource dosen't actually work, so you're confined
to using $http if you want to use `transformResponse`.
- `transformResponse` is run BEFORE $http interceptors, which makes it pretty useless
if you rely on $http interceptors for authorization (e.g.
[angular-http-auth](https://github.com/witoldsz/angular-http-auth) )
A better solution is to define a $resource in your service, call it, and deserialize
the response in a success callback within your service. Use a promise to return the
result of the deserialization.
Any better ideas?
-----------------
I'm no Javascript/angular pro, so if you have any better ideas for how to achieve
the same thing, please comment on the
[SO question](http://stackoverflow.com/questions/25532536/angular-http-auth-with-http-transformresponse)
I asked about this.
{
"make": "Honda",
"model": "Civic",
"year": 2042,
"torque": "ungodly"
}