As mentioned earlier,
Angulyar provides the $ resource class to increase the level of abstraction between client-side code and the server API . Therefore, it is now quite easy to perform CRUD operations over the network. But what happens when you need to execute a command for a RESTful resource that goes beyond the standard CRUD methods (i.e. create, read, update, delete)? Fortunately, Angulyar works quite well with RESTful "controllers".
In accordance with the
Mark Masse REST Code , there are four resource archetypes:
- Document - a resource view.
- Collection - a set of data on the server.
- Storage - a set of data on the client.
- The controller is the action to be performed.
Document, Collection and Storage represent resources. Controllers, on the other hand, are responsible for changing resources. You can use verbs in HTTP to indicate action on a resource, but for mediocre CRUD operations this does not always make sense. Take the following resources as an example:
')
Having a message collection (the first resource) and a separate message (the second resource), how to report on the clearing of all messages? Or how to move this message to the archive? CRUD does not quite meet these requirements. But controllers are great for operations of this type:
- / messages / clear-all
- / messages / 4 / archive
Here we use the “clear-all” and “archive” Controllers to modify the Collection and Archiving of the Document, respectively.
Starting to use controllers for our resources, we came to the URL scheme, which has great variability. Angular's $ resource allows you to do this, but you'll have to use a few “smart” features to customize the data binding.
Based on the above concept of working with messages, in the context of Angular we would have to define our resource using the following template:
- / messages /: id /: controller
The problem is that, currently, there is some ambiguity around the first URL parameter. Is the ": id" reference to the Collection-based Controller? Or is this a Document ID link?
To eliminate this uncertainty, Angulyar allows you to define several parameters in the same part of the template URL:
- / messages /: listController: id /: docController
Note that the second part of the URL pattern contains two parameters:
So far I use only one of them, while Angulyar will build a RESTful resource properly. To demonstrate this, I wrote a demo in which the message resource is defined and then used as shown above:
<!doctype html> <html ng-app="Demo"> <head> <meta charset="utf-8" /> <title> RESTful AngularJS</title> <script type="text/javascript" src="../angular-1.0.2/angular.js"></script> <script type="text/javascript" src="../angular-1.0.2/angular-resource.js"></script> <script type="text/javascript"> </script> </head> <body> </body> </html>
Please note that my Angulean resource is viewed by two different controllers:
- : ListController - acts on a collection of messages.
- : DocController - acts on a specific message.
When resource methods were involved above, then, ultimately, four requests were made to the following addresses:
As you can see, Angulyar correctly identified the URLs according to the REST. Kayf!
If interested, here is the test API file:
<cfset resourcePath = cgi.path_info /> <cfif ( cgi.request_method neq "GET" )> <cfset requestBody = getHTTPRequestData().content /> </cfif> <cfif reFind( "^/messages$", resourcePath )> <cfset response = "GET without ID." /> <cfelseif reFind( "^/messages/clear-all$", resourcePath )> <cfset response = "POST with clear-all Controller." /> <cfelseif reFind( "^/messages/\d+$", resourcePath )> <cfset response = "GET with ID." /> <cfelseif reFind( "^/messages/\d+/archive+$", resourcePath )> <cfset response = "POST with archive controller" /> <cfelse> <cfset response = "Hmm, couldn't match resource." /> </cfif> <cfset serializedResponse = serializeJSON( response ) /> <cfheader name="X-Debug-Path" value="#cgi.path_info#" /> <cfcontent type="application/json" variable="#charsetDecode( serializedResponse, 'utf-8' )#" />
For some reason, ColdFusion 10 hung up on POST requests, until I got access to the request body (via the getHttpRequestData () function). This happened only if the request body contained JSON (JavaScript Object Notation) data. When it was empty, the query did not hang. I don’t understand thoroughly the processing of requests and I don’t know if it makes sense, however, I’ll note that ColdFusion 9 doesn’t do that.
Original