248 lines
16 KiB
HTML
Executable file
248 lines
16 KiB
HTML
Executable file
<a href="http://github.com/angular/angular.js/tree/v1.2.0rc1/src/ngResource/resource.js#L21" class="view-source btn btn-action"><i class="icon-zoom-in"> </i> View source</a><a href="http://github.com/angular/angular.js/edit/master/src/ngResource/resource.js" class="improve-docs btn btn-primary"><i class="icon-edit"> </i> Improve this doc</a><h1><code ng:non-bindable="">$resource</code>
|
||
<div><span class="hint">service in module <code ng:non-bindable="">ngResource</code>
|
||
</span>
|
||
</div>
|
||
</h1>
|
||
<div><h2 id="Description">Description</h2>
|
||
<div class="description"><div class="ngresource-resource-page"><p>A factory which creates a resource object that lets you interact with
|
||
<a href="http://en.wikipedia.org/wiki/Representational_State_Transfer">RESTful</a> server-side data sources.</p>
|
||
<p>The returned resource object has action methods which provide high-level behaviors without
|
||
the need to interact with the low level <a href="api/ng.$http"><code>$http</code></a> service.</p>
|
||
<p>Requires the <a href="api/ngResource"><code>ngResource</code></a> module to be installed.</p>
|
||
</div></div>
|
||
<h2 id="Dependencies">Dependencies</h2>
|
||
<ul class="dependencies"><li><code ng:non-bindable=""><a href="api/ng.$http">$http</a></code>
|
||
</li>
|
||
</ul>
|
||
<h2 id="Usage">Usage</h2>
|
||
<div class="usage"><pre class="prettyprint linenums">$resource(url[, paramDefaults][, actions]);</pre>
|
||
<h4 id="parameters">Parameters</h4><table class="variables-matrix table table-bordered table-striped"><thead><tr><th>Param</th><th>Type</th><th>Details</th></tr></thead><tbody><tr><td>url</td><td><a href="" class="label type-hint type-hint-string">string</a></td><td><div class="ngresource-resource-page"><p>A parametrized URL template with parameters prefixed by <code>:</code> as in
|
||
<code>/user/:username</code>. If you are using a URL with a port number (e.g.
|
||
<code>http://example.com:8080/api</code>), it will be respected.</p>
|
||
<p>If you are using a url with a suffix, just add the suffix, like this:
|
||
<code>$resource('http://example.com/resource.json')</code> or <code>$resource('http://example.com/:id.json')</code>
|
||
or even <code>$resource('http://example.com/resource/:resource_id.:format')</code>
|
||
If the parameter before the suffix is empty, :resource_id in this case, then the <code>/.</code> will be
|
||
collapsed down to a single <code>.</code>. If you need this sequence to appear and not collapse then you
|
||
can escape it with <code>/\.</code>.</p>
|
||
</div></td></tr><tr><td>paramDefaults <div><em>(optional)</em></div></td><td><a href="" class="label type-hint type-hint-object">Object</a></td><td><div class="ngresource-resource-page"><p>Default values for <code>url</code> parameters. These can be overridden in
|
||
<code>actions</code> methods. If any of the parameter value is a function, it will be executed every time
|
||
when a param value needs to be obtained for a request (unless the param was overridden).</p>
|
||
<p>Each key value in the parameter object is first bound to url template if present and then any
|
||
excess keys are appended to the url search query after the <code>?</code>.</p>
|
||
<p>Given a template <code>/path/:verb</code> and parameter <code>{verb:'greet', salutation:'Hello'}</code> results in
|
||
URL <code>/path/greet?salutation=Hello</code>.</p>
|
||
<p>If the parameter value is prefixed with <code>@</code> then the value of that parameter is extracted from
|
||
the data object (useful for non-GET operations).</p>
|
||
</div></td></tr><tr><td>actions <div><em>(optional)</em></div></td><td><a href="" class="label type-hint type-hint-object">Object.<Object></a></td><td><div class="ngresource-resource-page"><p>Hash with declaration of custom action that should extend the
|
||
default set of resource actions. The declaration should be created in the format of <a href="api/ng.$http#Parameters"><code>$http.config</code></a>:</p>
|
||
<pre><code>{action1: {method:?, params:?, isArray:?, headers:?, ...},
|
||
action2: {method:?, params:?, isArray:?, headers:?, ...},
|
||
...}</code></pre>
|
||
<p>Where:</p>
|
||
<ul>
|
||
<li><strong><code>action</code></strong> – {string} – The name of action. This name becomes the name of the method on your
|
||
resource object.</li>
|
||
<li><strong><code>method</code></strong> – {string} – HTTP request method. Valid methods are: <code>GET</code>, <code>POST</code>, <code>PUT</code>, <code>DELETE</code>,
|
||
and <code>JSONP</code>.</li>
|
||
<li><strong><code>params</code></strong> – {Object=} – Optional set of pre-bound parameters for this action. If any of the
|
||
parameter value is a function, it will be executed every time when a param value needs to be
|
||
obtained for a request (unless the param was overridden).</li>
|
||
<li><strong><code>url</code></strong> – {string} – action specific <code>url</code> override. The url templating is supported just like
|
||
for the resource-level urls.</li>
|
||
<li><strong><code>isArray</code></strong> – {boolean=} – If true then the returned object for this action is an array, see
|
||
<code>returns</code> section.</li>
|
||
<li><strong><code>transformRequest</code></strong> – <code>{function(data, headersGetter)|Array.<function(data, headersGetter)>}</code> –
|
||
transform function or an array of such functions. The transform function takes the http
|
||
request body and headers and returns its transformed (typically serialized) version.</li>
|
||
<li><strong><code>transformResponse</code></strong> – <code>{function(data, headersGetter)|Array.<function(data, headersGetter)>}</code> –
|
||
transform function or an array of such functions. The transform function takes the http
|
||
response body and headers and returns its transformed (typically deserialized) version.</li>
|
||
<li><strong><code>cache</code></strong> – <code>{boolean|Cache}</code> – If true, a default $http cache will be used to cache the
|
||
GET request, otherwise if a cache instance built with
|
||
<a href="api/ng.$cacheFactory"><code>$cacheFactory</code></a>, this cache will be used for
|
||
caching.</li>
|
||
<li><strong><code>timeout</code></strong> – <code>{number|Promise}</code> – timeout in milliseconds, or <a href="api/ng.$q"><code>promise</code></a> that
|
||
should abort the request when resolved.</li>
|
||
<li><strong><code>withCredentials</code></strong> - <code>{boolean}</code> - whether to to set the <code>withCredentials</code> flag on the
|
||
XHR object. See <a href="https://developer.mozilla.org/en/http_access_control#section_5">requests with credentials</a> for more information.</li>
|
||
<li><strong><code>responseType</code></strong> - <code>{string}</code> - see <a href="https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType">requestType</a>.</li>
|
||
<li><strong><code>interceptor</code></strong> - <code>{Object=}</code> - The interceptor object has two optional methods -
|
||
<code>response</code> and <code>responseError</code>. Both <code>response</code> and <code>responseError</code> interceptors get called
|
||
with <code>http response</code> object. See <a href="api/ng.$http"><code>$http interceptors</code></a>.</li>
|
||
</ul>
|
||
</div></td></tr></tbody></table><h4 id="returns">Returns</h4><table class="variables-matrix"><tr><td><a href="" class="label type-hint type-hint-object">Object</a></td><td><div class="ngresource-resource-page"><p>A resource "class" object with methods for the default set of resource actions
|
||
optionally extended with custom <code>actions</code>. The default set contains these actions:</p>
|
||
<pre><code>{ 'get': {method:'GET'},
|
||
'save': {method:'POST'},
|
||
'query': {method:'GET', isArray:true},
|
||
'remove': {method:'DELETE'},
|
||
'delete': {method:'DELETE'} };</code></pre>
|
||
<p>Calling these methods invoke an <a href="api/ng.$http"><code>ng.$http</code></a> with the specified http method,
|
||
destination and parameters. When the data is returned from the server then the object is an
|
||
instance of the resource class. The actions <code>save</code>, <code>remove</code> and <code>delete</code> are available on it
|
||
as methods with the <code>$</code> prefix. This allows you to easily perform CRUD operations (create,
|
||
read, update, delete) on server-side data like this:
|
||
<pre class="prettyprint linenums">
|
||
var User = $resource('/user/:userId', {userId:'@id'});
|
||
var user = User.get({userId:123}, function() {
|
||
user.abc = true;
|
||
user.$save();
|
||
});
|
||
</pre>
|
||
<p>It is important to realize that invoking a $resource object method immediately returns an
|
||
empty reference (object or array depending on <code>isArray</code>). Once the data is returned from the
|
||
server the existing reference is populated with the actual data. This is a useful trick since
|
||
usually the resource is assigned to a model which is then rendered by the view. Having an empty
|
||
object results in no rendering, once the data arrives from the server then the object is
|
||
populated with the data and the view automatically re-renders itself showing the new data. This
|
||
means that in most case one never has to write a callback function for the action methods.</p>
|
||
<p>The action methods on the class object or instance object can be invoked with the following
|
||
parameters:</p>
|
||
<ul>
|
||
<li>HTTP GET "class" actions: <code>Resource.action([parameters], [success], [error])</code></li>
|
||
<li>non-GET "class" actions: <code>Resource.action([parameters], postData, [success], [error])</code></li>
|
||
<li>non-GET instance actions: <code>instance.$action([parameters], [success], [error])</code></li>
|
||
</ul>
|
||
<p>Success callback is called with (value, responseHeaders) arguments. Error callback is called
|
||
with (httpResponse) argument.</p>
|
||
<p>Class actions return empty instance (with additional properties below).
|
||
Instance actions return promise of the action.</p>
|
||
<p>The Resource instances and collection have these additional properties:</p>
|
||
<ul>
|
||
<li><p><code>$promise</code>: the <a href="api/ng.$q"><code>promise</code></a> of the original server interaction that created this
|
||
instance or collection.</p>
|
||
<p>On success, the promise is resolved with the same resource instance or collection object,
|
||
updated with data from server. This makes it easy to use in
|
||
<a href="api/ngRoute.$routeProvider">resolve section of $routeProvider.when()</a> to defer view rendering
|
||
until the resource(s) are loaded.</p>
|
||
<p>On failure, the promise is resolved with the <a href="api/ng.$http"><code>http response</code></a> object,
|
||
without the <code>resource</code> property.</p>
|
||
</li>
|
||
<li><p><code>$resolved</code>: <code>true</code> after first server interaction is completed (either with success or rejection),
|
||
<code>false</code> before that. Knowing if the Resource has been resolved is useful in data-binding.</p>
|
||
</li>
|
||
</ul>
|
||
</div></td></tr></table></div>
|
||
<h2 id="Example">Example</h2>
|
||
<div class="example"><div class="ngresource-resource-page"><h3>Credit card resource</h1>
|
||
<pre class="prettyprint linenums">
|
||
// Define CreditCard class
|
||
var CreditCard = $resource('/user/:userId/card/:cardId',
|
||
{userId:123, cardId:'@id'}, {
|
||
charge: {method:'POST', params:{charge:true}}
|
||
});
|
||
|
||
// We can retrieve a collection from the server
|
||
var cards = CreditCard.query(function() {
|
||
// GET: /user/123/card
|
||
// server returns: [ {id:456, number:'1234', name:'Smith'} ];
|
||
|
||
var card = cards[0];
|
||
// each item is an instance of CreditCard
|
||
expect(card instanceof CreditCard).toEqual(true);
|
||
card.name = "J. Smith";
|
||
// non GET methods are mapped onto the instances
|
||
card.$save();
|
||
// POST: /user/123/card/456 {id:456, number:'1234', name:'J. Smith'}
|
||
// server returns: {id:456, number:'1234', name: 'J. Smith'};
|
||
|
||
// our custom method is mapped as well.
|
||
card.$charge({amount:9.99});
|
||
// POST: /user/123/card/456?amount=9.99&charge=true {id:456, number:'1234', name:'J. Smith'}
|
||
});
|
||
|
||
// we can create an instance as well
|
||
var newCard = new CreditCard({number:'0123'});
|
||
newCard.name = "Mike Smith";
|
||
newCard.$save();
|
||
// POST: /user/123/card {number:'0123', name:'Mike Smith'}
|
||
// server returns: {id:789, number:'01234', name: 'Mike Smith'};
|
||
expect(newCard.id).toEqual(789);
|
||
</pre>
|
||
<p>The object returned from this function execution is a resource "class" which has "static" method
|
||
for each action in the definition.</p>
|
||
<p>Calling these methods invoke <code>$http</code> on the <code>url</code> template with the given <code>method</code>, <code>params</code> and <code>headers</code>.
|
||
When the data is returned from the server then the object is an instance of the resource type and
|
||
all of the non-GET methods are available with <code>$</code> prefix. This allows you to easily support CRUD
|
||
operations (create, read, update, delete) on server-side data.</p>
|
||
<p> <pre class="prettyprint linenums">
|
||
var User = $resource('/user/:userId', {userId:'@id'});
|
||
var user = User.get({userId:123}, function() {
|
||
user.abc = true;
|
||
user.$save();
|
||
});
|
||
</pre>
|
||
<p>It's worth noting that the success callback for <code>get</code>, <code>query</code> and other method gets passed
|
||
in the response that came from the server as well as $http header getter function, so one
|
||
could rewrite the above example and get access to http headers as:</p>
|
||
<p> <pre class="prettyprint linenums">
|
||
var User = $resource('/user/:userId', {userId:'@id'});
|
||
User.get({userId:123}, function(u, getResponseHeaders){
|
||
u.abc = true;
|
||
u.$save(function(u, putResponseHeaders) {
|
||
//u => saved user object
|
||
//putResponseHeaders => $http header getter
|
||
});
|
||
});
|
||
</pre>
|
||
<h1>Buzz client</h1>
|
||
<p> Let's look at what a buzz client created with the <code>$resource</code> service looks like:
|
||
<h4>Source</h2>
|
||
<div source-edit="" source-edit-deps="angular.js script.js" source-edit-html="index.html-143" source-edit-css="" source-edit-js="script.js-142" source-edit-json="" source-edit-unit="" source-edit-scenario="scenario.js-144"></div>
|
||
<div class="tabbable"><div class="tab-pane" title="index.html">
|
||
<pre class="prettyprint linenums" ng-set-text="index.html-143" ng-html-wrap=" angular.js script.js"></pre>
|
||
<script type="text/ng-template" id="index.html-143">
|
||
|
||
|
||
<div ng-controller="BuzzController">
|
||
<input ng-model="userId"/>
|
||
<button ng-click="fetch()">fetch</button>
|
||
<hr/>
|
||
<div ng-repeat="item in activities.data.items">
|
||
<h1 style="font-size: 15px;">
|
||
<img src="{{item.actor.thumbnailUrl}}" style="max-height:30px;max-width:30px;"/>
|
||
<a href="{{item.actor.profileUrl}}">{{item.actor.name}}</a>
|
||
<a href ng-click="expandReplies(item)" style="float: right;">Expand replies: {{item.links.replies[0].count}}</a>
|
||
</h3>
|
||
{{item.object.content | html}}
|
||
<div ng-repeat="reply in item.replies.data.items" style="margin-left: 20px;">
|
||
<img src="{{reply.actor.thumbnailUrl}}" style="max-height:30px;max-width:30px;"/>
|
||
<a href="{{reply.actor.profileUrl}}">{{reply.actor.name}}</a>: {{reply.content | html}}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</script>
|
||
</div>
|
||
<div class="tab-pane" title="script.js">
|
||
<pre class="prettyprint linenums" ng-set-text="script.js-142"></pre>
|
||
<script type="text/ng-template" id="script.js-142">
|
||
function BuzzController($resource) {
|
||
this.userId = 'googlebuzz';
|
||
this.Activity = $resource(
|
||
'https://www.googleapis.com/buzz/v1/activities/:userId/:visibility/:activityId/:comments',
|
||
{alt:'json', callback:'JSON_CALLBACK'},
|
||
{get:{method:'JSONP', params:{visibility:'@self'}}, replies: {method:'JSONP', params:{visibility:'@self', comments:'@comments'}}}
|
||
);
|
||
}
|
||
|
||
BuzzController.prototype = {
|
||
fetch: function() {
|
||
this.activities = this.Activity.get({userId:this.userId});
|
||
},
|
||
expandReplies: function(activity) {
|
||
activity.replies = this.Activity.replies({userId:this.userId, activityId:activity.id});
|
||
}
|
||
};
|
||
BuzzController.$inject = ['$resource'];
|
||
</script>
|
||
</div>
|
||
<div class="tab-pane" title="End to end test">
|
||
<pre class="prettyprint linenums" ng-set-text="scenario.js-144"></pre>
|
||
<script type="text/ng-template" id="scenario.js-144">
|
||
</script>
|
||
</div>
|
||
</div><h2>Demo</h4>
|
||
<div class="well doc-example-live animate-container" ng-embed-app="" ng-set-html="index.html-143" ng-eval-javascript="script.js-142"></div>
|
||
</div></div>
|
||
</div>
|