Effectively Managing Resources (Models) in Your Angular.js Based Single Page Application
by Himanshu Kapoor, Front-end Engineer, Wingify
Web: fleon.org, Twitter: @himkp, Email: [email protected]
This presentation: http://lab.fleon.org/angularjs-and-resources/
Download / Fork on GitHub: https://github.com/fleon/angularjs-and-resources
+
+
Why should you make Single Page Apps?
with Angular.js + Angular UI Router + Require.js
Views: rendered in the browser
Controllers: makes your view dynamic, has the logic
Models: plain old POJOs
Yes, Plain Old Javascript Objects!
Hmm, sounds cool!
function MyCtrl($scope) {
$scope.myModel = 'hello world';
}
{{myModel}}
// myModel is a POJO model
$http shall answer all our queries
function MyCtrl($scope, $http) {
$http.get('/user').success(function (user) {
$scope.user = user;
});
}
Hello there, {{user.name}}
{ // HTTP GET Response
"id": 1234,
"name": "John Doe",
"email": "[email protected]"
}
Pretty sweet, right?
Back in the real world, things aren't so simple.
How do you make sure your code is:
app.factory('UserResource', function () {
return $resource('/user/:userId', {
userId: '@id'
});
});
function MyCtrl($scope, UserResource) {
$scope.user = UserResource.get({
id: 1
});
}
Hello there, {{user.name}}
Looks no different from the previous output,
but our code is a lot more extendible with the above logic.
In addition to the code we already have:
app.factory('UserResource', function () {
return $resource('/user/:userId', {
userId: '@id'
});
});
function MyCtrl($scope, UserResource) {
$scope.user = UserResource.get({
id: 1
});
}
Hello there, {{user.name}}
Let us add another view that does something else, and something more...
Edit your name
function MyEditCtrl($scope, UserResource) {
$scope.user = UserResource.get({
id: 1
});
$scope.updateName = function () {
$scope.user.name = $scope.newName;
$scope.user.$save();
};
}
Separation of concerns is good, but not if it leads to such an inconsistency.
author
~ post
, author
~ comment
post.author
is an AuthorResource
, author.posts
is a collection of PostResource
sMaintaining references
Maintaining references: Ensuring that each unique resource has only one instance throughout the app.
For instance, there should be only one instance of:
Q. How are such references maintained?
A. By transforming each backend response.
// GET /posts
[{
"id": 1,
"createdBy": { "id": 1, "name": "John Doe" }
"title": "My First Post",
"excerpt": "Lorem Ipsum"
}, {
"id": 2,
"createdBy": { "id": 1, "name": "John Doe" }
"title": "My Second Post",
"excerpt": "Lorem Ipsum"
}, {
"id": 3,
"createdBy": { "id": 1, "name": "Jony Ive" }
"title": "My Third Post",
"excerpt": "Lorem Ipsum"
}]
// Output obtained by transforming the response above
var output = /* ... */;
expect(output).toEqual(any(Array));
expect(output.length).toBe(3);
expect(output[0]).toEqual(any(PostResource))
expect(output[1]).toEqual(any(PostResource))
expect(output[2]).toEqual(any(PostResource))
expect(output[0].createdBy).toBe(output[1].createdBy);
expect(output[0].createdBy).toBe(output[2].createdBy);
How?
An abstracted base that every resource stands on that is:
Prevention of mixing resource management logic with the business logic
The core logic stays at a single place
The result: ResourceManager