NgResource
CRUD without boilerplate
Objectives
-
Replace RESTful $http requests with ng-resource
- Appreciate the power of the REST standard
Refresher - Whats REST?
-
"Representational State Transfer"
- Maps actions to HTTP verbs (GET, POST, PUT, PATCH, DELETE)
- Standard URL design
- Client/Server && "Separation of Concerns"
-
Ultimately, REST is a design pattern. When we follow a shared design, we can use shared tools.
Verbs, URLS, and REST
URLs follow a pattern: host/api-base/{collection}/{id}
collections and individual items behave differently:
$http + REST
getTodos: function(){
return $http.get("/api/todos"); // get whole collection
},
createTodo: function(todo){
return $http.post("/api/todos", todo); // create new todo
},
getTodo: function(id){
return $http.get("/api/todos/" + id); // get single todo
},
editTodo: function(id,todo){
return $http.put("/api/todos/" + id, todo); // update single todo
},
deleteTodo: function(id){
return $http.delete("/api/todos/" + id); // delete single todo
}
For example, if I were using $http and my database had a table called todo:
$resource + REST
angular.module("todoApp", ['ngRoute','ngResource']);
// ...
angular.module("todoApp").controller($scope, $resource) {
var todoResource = $resource('/api/todos/:id', { id: '@id' });
}
Because we are allowed to assume the server code is REST compliant, here is the same featureset with $resource
Booyah.
$resource
$resource('/api/todos/:id', { id: '@id' });
So, whats happening here?
Resource URL on our API
URL parameter, filled out based on the object passed to my resource
When prefixed with @: The name of the property which will be mapped into the :id url field.
This can also be a static value.
$resource + REST
var todoResource = $resource('/api/todos/:id', { id: '@id' });
// envoking a $resource returns an object.
var myTodo = todoResource.get({id: 1}, function(todo) {
console.log(todo === myTodo) // true
// You can use the object in cool ways:
myTodo.newProperty = "Bang, new prop!";
// POST myTodo JSON to /api/todos/1
// This one isnt quite right...
myTodo.$save();
// DELETE resourceTodo JSON to /api/todos/1
myTodo.$delete();
});
var arbitraryFrontEndTodo = {task: "DO ALL THE THINGS"};
todoResource.save(arbitraryFrontEndTodo) // POST arbitraryFrontEndTodo JSON to /api/todos
So how do I use it?
Getting to PUT
// POST resourceTodo JSON to /api/todos/1
// This one isnt quite right...
resourceTodo.$save();
// This POSTS to /api/todos which is correct
// We also let the DB decide what id this new obj should get
var arbitraryFrontEndTodo = {task: "DO ALL THE THINGS"};
todoResource.$save(arbitraryFrontEndTodo) // POST the todo JSON to /api/todos
Recall from four slides ago, to save an individual resource that has an id already we're supposed to use PUT.
Getting to PUT
var todoResource = $resource('/api/todos/:id', { id: '@id' }, {
update: {
method: 'PUT' // this method issues a PUT request
}
});
var myTodo = todoResource.get({id: 1}, function(todo) {
console.log(todo === resourceTodo) // true
// You can use the object in cool ways:
myTodo.newProperty = "Bang, new prop!";
// PUT resourceTodo JSON to /api/todos/1
myTodo.$update();
}
All we have to do is give an additional method when we construct the resource
Questions?
ng-resource
By Tyler Bettilyon
ng-resource
- 1,417