angularjs-rails 1.6.8 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  /**
2
- * @license AngularJS v1.6.8
3
- * (c) 2010-2017 Google, Inc. http://angularjs.org
2
+ * @license AngularJS v1.8.0
3
+ * (c) 2010-2020 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
6
6
  (function(window, angular) {'use strict';
@@ -1229,15 +1229,21 @@ function IDC_Y(cp) {
1229
1229
  * @ngdoc module
1230
1230
  * @name ngParseExt
1231
1231
  * @packageName angular-parse-ext
1232
+ *
1232
1233
  * @description
1233
1234
  *
1234
1235
  * The `ngParseExt` module provides functionality to allow Unicode characters in
1235
- * identifiers inside Angular expressions.
1236
+ * identifiers inside AngularJS expressions.
1236
1237
  *
1237
1238
  * This module allows the usage of any identifier that follows ES6 identifier naming convention
1238
- * to be used as an identifier in an Angular expression. ES6 delegates some of the identifier
1239
+ * to be used as an identifier in an AngularJS expression. ES6 delegates some of the identifier
1239
1240
  * rules definition to Unicode, this module uses ES6 and Unicode 8.0 identifiers convention.
1240
1241
  *
1242
+ * <div class="alert alert-warning">
1243
+ * You cannot use Unicode characters for variable names in the {@link ngRepeat} or {@link ngOptions}
1244
+ * expressions (e.g. `ng-repeat="f in поля"`), because even with `ngParseExt` included, these
1245
+ * special expressions are not parsed by the {@link $parse} service.
1246
+ * </div>
1241
1247
  */
1242
1248
 
1243
1249
  /* global angularParseExtModule: true,
@@ -1263,7 +1269,7 @@ angular.module('ngParseExt', [])
1263
1269
  .config(['$parseProvider', function($parseProvider) {
1264
1270
  $parseProvider.setIdentifierFns(isValidIdentifierStart, isValidIdentifierContinue);
1265
1271
  }])
1266
- .info({ angularVersion: '1.6.8' });
1272
+ .info({ angularVersion: '1.8.0' });
1267
1273
 
1268
1274
 
1269
1275
  })(window, window.angular);
@@ -1,6 +1,6 @@
1
1
  /**
2
- * @license AngularJS v1.6.8
3
- * (c) 2010-2017 Google, Inc. http://angularjs.org
2
+ * @license AngularJS v1.8.0
3
+ * (c) 2010-2020 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
6
6
  (function(window, angular) {'use strict';
@@ -115,13 +115,13 @@ function shallowClearAndCopy(src, dst) {
115
115
  *
116
116
  * @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in
117
117
  * `actions` methods. If a parameter value is a function, it will be called every time
118
- * a param value needs to be obtained for a request (unless the param was overridden). The function
119
- * will be passed the current data value as an argument.
118
+ * a param value needs to be obtained for a request (unless the param was overridden). The
119
+ * function will be passed the current data value as an argument.
120
120
  *
121
121
  * Each key value in the parameter object is first bound to url template if present and then any
122
122
  * excess keys are appended to the url search query after the `?`.
123
123
  *
124
- * Given a template `/path/:verb` and parameter `{verb:'greet', salutation:'Hello'}` results in
124
+ * Given a template `/path/:verb` and parameter `{verb: 'greet', salutation: 'Hello'}` results in
125
125
  * URL `/path/greet?salutation=Hello`.
126
126
  *
127
127
  * If the parameter value is prefixed with `@`, then the value for that parameter will be
@@ -130,7 +130,7 @@ function shallowClearAndCopy(src, dst) {
130
130
  * For example, if the `defaultParam` object is `{someParam: '@someProp'}` then the value of
131
131
  * `someParam` will be `data.someProp`.
132
132
  * Note that the parameter will be ignored, when calling a "GET" action method (i.e. an action
133
- * method that does not accept a request body)
133
+ * method that does not accept a request body).
134
134
  *
135
135
  * @param {Object.<Object>=} actions Hash with declaration of custom actions that will be available
136
136
  * in addition to the default set of resource actions (see below). If a custom action has the same
@@ -139,9 +139,11 @@ function shallowClearAndCopy(src, dst) {
139
139
  *
140
140
  * The declaration should be created in the format of {@link ng.$http#usage $http.config}:
141
141
  *
142
- * {action1: {method:?, params:?, isArray:?, headers:?, ...},
143
- * action2: {method:?, params:?, isArray:?, headers:?, ...},
144
- * ...}
142
+ * {
143
+ * action1: {method:?, params:?, isArray:?, headers:?, ...},
144
+ * action2: {method:?, params:?, isArray:?, headers:?, ...},
145
+ * ...
146
+ * }
145
147
  *
146
148
  * Where:
147
149
  *
@@ -153,54 +155,58 @@ function shallowClearAndCopy(src, dst) {
153
155
  * the parameter value is a function, it will be called every time when a param value needs to
154
156
  * be obtained for a request (unless the param was overridden). The function will be passed the
155
157
  * current data value as an argument.
156
- * - **`url`** – {string} – action specific `url` override. The url templating is supported just
158
+ * - **`url`** – {string} – Action specific `url` override. The url templating is supported just
157
159
  * like for the resource-level urls.
158
160
  * - **`isArray`** – {boolean=} – If true then the returned object for this action is an array,
159
161
  * see `returns` section.
160
162
  * - **`transformRequest`** –
161
163
  * `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –
162
- * transform function or an array of such functions. The transform function takes the http
164
+ * Transform function or an array of such functions. The transform function takes the http
163
165
  * request body and headers and returns its transformed (typically serialized) version.
164
166
  * By default, transformRequest will contain one function that checks if the request data is
165
167
  * an object and serializes it using `angular.toJson`. To prevent this behavior, set
166
168
  * `transformRequest` to an empty array: `transformRequest: []`
167
169
  * - **`transformResponse`** –
168
170
  * `{function(data, headersGetter, status)|Array.<function(data, headersGetter, status)>}` –
169
- * transform function or an array of such functions. The transform function takes the http
171
+ * Transform function or an array of such functions. The transform function takes the HTTP
170
172
  * response body, headers and status and returns its transformed (typically deserialized)
171
173
  * version.
172
174
  * By default, transformResponse will contain one function that checks if the response looks
173
175
  * like a JSON string and deserializes it using `angular.fromJson`. To prevent this behavior,
174
176
  * set `transformResponse` to an empty array: `transformResponse: []`
175
- * - **`cache`** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the
176
- * GET request, otherwise if a cache instance built with
177
- * {@link ng.$cacheFactory $cacheFactory} is supplied, this cache will be used for
178
- * caching.
179
- * - **`timeout`** – `{number}` – timeout in milliseconds.<br />
177
+ * - **`cache`** – `{boolean|Cache}` – A boolean value or object created with
178
+ * {@link ng.$cacheFactory `$cacheFactory`} to enable or disable caching of the HTTP response.
179
+ * See {@link $http#caching $http Caching} for more information.
180
+ * - **`timeout`** – `{number}` – Timeout in milliseconds.<br />
180
181
  * **Note:** In contrast to {@link ng.$http#usage $http.config}, {@link ng.$q promises} are
181
- * **not** supported in $resource, because the same value would be used for multiple requests.
182
+ * **not** supported in `$resource`, because the same value would be used for multiple requests.
182
183
  * If you are looking for a way to cancel requests, you should use the `cancellable` option.
183
- * - **`cancellable`** – `{boolean}` – if set to true, the request made by a "non-instance" call
184
- * will be cancelled (if not already completed) by calling `$cancelRequest()` on the call's
185
- * return value. Calling `$cancelRequest()` for a non-cancellable or an already
186
- * completed/cancelled request will have no effect.<br />
187
- * - **`withCredentials`** - `{boolean}` - whether to set the `withCredentials` flag on the
184
+ * - **`cancellable`** – `{boolean}` – If true, the request made by a "non-instance" call will be
185
+ * cancelled (if not already completed) by calling `$cancelRequest()` on the call's return
186
+ * value. Calling `$cancelRequest()` for a non-cancellable or an already completed/cancelled
187
+ * request will have no effect.
188
+ * - **`withCredentials`** `{boolean}` Whether to set the `withCredentials` flag on the
188
189
  * XHR object. See
189
- * [requests with credentials](https://developer.mozilla.org/en/http_access_control#section_5)
190
+ * [XMLHttpRequest.withCredentials](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials)
190
191
  * for more information.
191
- * - **`responseType`** - `{string}` - see
192
- * [requestType](https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType).
193
- * - **`interceptor`** - `{Object=}` - The interceptor object has two optional methods -
194
- * `response` and `responseError`. Both `response` and `responseError` interceptors get called
195
- * with `http response` object. See {@link ng.$http $http interceptors}. In addition, the
196
- * resource instance or array object is accessible by the `resource` property of the
197
- * `http response` object.
192
+ * - **`responseType`** `{string}` See
193
+ * [XMLHttpRequest.responseType](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseType).
194
+ * - **`interceptor`** `{Object=}` The interceptor object has four optional methods -
195
+ * `request`, `requestError`, `response`, and `responseError`. See
196
+ * {@link ng.$http#interceptors $http interceptors} for details. Note that
197
+ * `request`/`requestError` interceptors are applied before calling `$http`, thus before any
198
+ * global `$http` interceptors. Also, rejecting or throwing an error inside the `request`
199
+ * interceptor will result in calling the `responseError` interceptor.
200
+ * The resource instance or collection is available on the `resource` property of the
201
+ * `http response` object passed to `response`/`responseError` interceptors.
198
202
  * Keep in mind that the associated promise will be resolved with the value returned by the
199
- * response interceptor, if one is specified. The default response interceptor returns
200
- * `response.resource` (i.e. the resource instance or array).
201
- * - **`hasBody`** - `{boolean}` - allows to specify if a request body should be included or not.
202
- * If not specified only POST, PUT and PATCH requests will have a body.
203
- *
203
+ * response interceptors. Make sure you return an appropriate value and not the `response`
204
+ * object passed as input. For reference, the default `response` interceptor (which gets applied
205
+ * if you don't specify a custom one) returns `response.resource`.<br />
206
+ * See {@link ngResource.$resource#using-interceptors below} for an example of using
207
+ * interceptors in `$resource`.
208
+ * - **`hasBody`** – `{boolean}` – If true, then the request will have a body.
209
+ * If not specified, then only POST, PUT and PATCH requests will have a body. *
204
210
  * @param {Object} options Hash with custom settings that should extend the
205
211
  * default `$resourceProvider` behavior. The supported options are:
206
212
  *
@@ -213,27 +219,29 @@ function shallowClearAndCopy(src, dst) {
213
219
  * @returns {Object} A resource "class" object with methods for the default set of resource actions
214
220
  * optionally extended with custom `actions`. The default set contains these actions:
215
221
  * ```js
216
- * { 'get': {method:'GET'},
217
- * 'save': {method:'POST'},
218
- * 'query': {method:'GET', isArray:true},
219
- * 'remove': {method:'DELETE'},
220
- * 'delete': {method:'DELETE'} };
222
+ * {
223
+ * 'get': {method: 'GET'},
224
+ * 'save': {method: 'POST'},
225
+ * 'query': {method: 'GET', isArray: true},
226
+ * 'remove': {method: 'DELETE'},
227
+ * 'delete': {method: 'DELETE'}
228
+ * }
221
229
  * ```
222
230
  *
223
- * Calling these methods invoke an {@link ng.$http} with the specified http method,
224
- * destination and parameters. When the data is returned from the server then the object is an
225
- * instance of the resource class. The actions `save`, `remove` and `delete` are available on it
226
- * as methods with the `$` prefix. This allows you to easily perform CRUD operations (create,
227
- * read, update, delete) on server-side data like this:
231
+ * Calling these methods invoke {@link ng.$http} with the specified http method, destination and
232
+ * parameters. When the data is returned from the server then the object is an instance of the
233
+ * resource class. The actions `save`, `remove` and `delete` are available on it as methods with
234
+ * the `$` prefix. This allows you to easily perform CRUD operations (create, read, update,
235
+ * delete) on server-side data like this:
228
236
  * ```js
229
- * var User = $resource('/user/:userId', {userId:'@id'});
230
- * var user = User.get({userId:123}, function() {
237
+ * var User = $resource('/user/:userId', {userId: '@id'});
238
+ * User.get({userId: 123}).$promise.then(function(user) {
231
239
  * user.abc = true;
232
240
  * user.$save();
233
241
  * });
234
242
  * ```
235
243
  *
236
- * It is important to realize that invoking a $resource object method immediately returns an
244
+ * It is important to realize that invoking a `$resource` object method immediately returns an
237
245
  * empty reference (object or array depending on `isArray`). Once the data is returned from the
238
246
  * server the existing reference is populated with the actual data. This is a useful trick since
239
247
  * usually the resource is assigned to a model which is then rendered by the view. Having an empty
@@ -256,30 +264,31 @@ function shallowClearAndCopy(src, dst) {
256
264
  *
257
265
  *
258
266
  * Success callback is called with (value (Object|Array), responseHeaders (Function),
259
- * status (number), statusText (string)) arguments, where the value is the populated resource
267
+ * status (number), statusText (string)) arguments, where `value` is the populated resource
260
268
  * instance or collection object. The error callback is called with (httpResponse) argument.
261
269
  *
262
- * Class actions return empty instance (with additional properties below).
263
- * Instance actions return promise of the action.
270
+ * Class actions return an empty instance (with the additional properties listed below).
271
+ * Instance actions return a promise for the operation.
264
272
  *
265
273
  * The Resource instances and collections have these additional properties:
266
274
  *
267
- * - `$promise`: the {@link ng.$q promise} of the original server interaction that created this
275
+ * - `$promise`: The {@link ng.$q promise} of the original server interaction that created this
268
276
  * instance or collection.
269
277
  *
270
278
  * On success, the promise is resolved with the same resource instance or collection object,
271
- * updated with data from server. This makes it easy to use in
272
- * {@link ngRoute.$routeProvider resolve section of $routeProvider.when()} to defer view
279
+ * updated with data from server. This makes it easy to use in the
280
+ * {@link ngRoute.$routeProvider `resolve` section of `$routeProvider.when()`} to defer view
273
281
  * rendering until the resource(s) are loaded.
274
282
  *
275
283
  * On failure, the promise is rejected with the {@link ng.$http http response} object.
276
284
  *
277
285
  * If an interceptor object was provided, the promise will instead be resolved with the value
278
- * returned by the interceptor.
286
+ * returned by the response interceptor (on success) or responceError interceptor (on failure).
279
287
  *
280
288
  * - `$resolved`: `true` after first server interaction is completed (either with success or
281
289
  * rejection), `false` before that. Knowing if the Resource has been resolved is useful in
282
- * data-binding.
290
+ * data-binding. If there is a response/responseError interceptor and it returns a promise,
291
+ * `$resolved` will wait for that too.
283
292
  *
284
293
  * The Resource instances and collections have these additional methods:
285
294
  *
@@ -290,127 +299,134 @@ function shallowClearAndCopy(src, dst) {
290
299
  *
291
300
  * - `toJSON`: It returns a simple object without any of the extra properties added as part of
292
301
  * the Resource API. This object can be serialized through {@link angular.toJson} safely
293
- * without attaching Angular-specific fields. Notice that `JSON.stringify` (and
302
+ * without attaching AngularJS-specific fields. Notice that `JSON.stringify` (and
294
303
  * `angular.toJson`) automatically use this method when serializing a Resource instance
295
304
  * (see [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#toJSON%28%29_behavior)).
296
305
  *
297
306
  * @example
298
307
  *
299
- * ### Credit card resource
308
+ * ### Basic usage
300
309
  *
301
- * ```js
302
- // Define CreditCard class
303
- var CreditCard = $resource('/user/:userId/card/:cardId',
304
- {userId:123, cardId:'@id'}, {
305
- charge: {method:'POST', params:{charge:true}}
306
- });
310
+ ```js
311
+ // Define a CreditCard class
312
+ var CreditCard = $resource('/users/:userId/cards/:cardId',
313
+ {userId: 123, cardId: '@id'}, {
314
+ charge: {method: 'POST', params: {charge: true}}
315
+ });
307
316
 
308
317
  // We can retrieve a collection from the server
309
- var cards = CreditCard.query(function() {
310
- // GET: /user/123/card
311
- // server returns: [ {id:456, number:'1234', name:'Smith'} ];
318
+ var cards = CreditCard.query();
319
+ // GET: /users/123/cards
320
+ // server returns: [{id: 456, number: '1234', name: 'Smith'}]
312
321
 
322
+ // Wait for the request to complete
323
+ cards.$promise.then(function() {
313
324
  var card = cards[0];
314
- // each item is an instance of CreditCard
325
+
326
+ // Each item is an instance of CreditCard
315
327
  expect(card instanceof CreditCard).toEqual(true);
316
- card.name = "J. Smith";
317
- // non GET methods are mapped onto the instances
328
+
329
+ // Non-GET methods are mapped onto the instances
330
+ card.name = 'J. Smith';
318
331
  card.$save();
319
- // POST: /user/123/card/456 {id:456, number:'1234', name:'J. Smith'}
320
- // server returns: {id:456, number:'1234', name: 'J. Smith'};
332
+ // POST: /users/123/cards/456 {id: 456, number: '1234', name: 'J. Smith'}
333
+ // server returns: {id: 456, number: '1234', name: 'J. Smith'}
321
334
 
322
- // our custom method is mapped as well.
323
- card.$charge({amount:9.99});
324
- // POST: /user/123/card/456?amount=9.99&charge=true {id:456, number:'1234', name:'J. Smith'}
335
+ // Our custom method is mapped as well (since it uses POST)
336
+ card.$charge({amount: 9.99});
337
+ // POST: /users/123/cards/456?amount=9.99&charge=true {id: 456, number: '1234', name: 'J. Smith'}
325
338
  });
326
339
 
327
- // we can create an instance as well
328
- var newCard = new CreditCard({number:'0123'});
329
- newCard.name = "Mike Smith";
330
- newCard.$save();
331
- // POST: /user/123/card {number:'0123', name:'Mike Smith'}
332
- // server returns: {id:789, number:'0123', name: 'Mike Smith'};
333
- expect(newCard.id).toEqual(789);
334
- * ```
340
+ // We can create an instance as well
341
+ var newCard = new CreditCard({number: '0123'});
342
+ newCard.name = 'Mike Smith';
343
+
344
+ var savePromise = newCard.$save();
345
+ // POST: /users/123/cards {number: '0123', name: 'Mike Smith'}
346
+ // server returns: {id: 789, number: '0123', name: 'Mike Smith'}
347
+
348
+ savePromise.then(function() {
349
+ // Once the promise is resolved, the created instance
350
+ // is populated with the data returned by the server
351
+ expect(newCard.id).toEqual(789);
352
+ });
353
+ ```
335
354
  *
336
- * The object returned from this function execution is a resource "class" which has "static" method
337
- * for each action in the definition.
355
+ * The object returned from a call to `$resource` is a resource "class" which has one "static"
356
+ * method for each action in the definition.
338
357
  *
339
- * Calling these methods invoke `$http` on the `url` template with the given `method`, `params` and
340
- * `headers`.
358
+ * Calling these methods invokes `$http` on the `url` template with the given HTTP `method`,
359
+ * `params` and `headers`.
341
360
  *
342
361
  * @example
343
362
  *
344
- * ### User resource
363
+ * ### Accessing the response
345
364
  *
346
365
  * When the data is returned from the server then the object is an instance of the resource type and
347
366
  * all of the non-GET methods are available with `$` prefix. This allows you to easily support CRUD
348
367
  * operations (create, read, update, delete) on server-side data.
349
-
368
+ *
350
369
  ```js
351
- var User = $resource('/user/:userId', {userId:'@id'});
352
- User.get({userId:123}, function(user) {
370
+ var User = $resource('/users/:userId', {userId: '@id'});
371
+ User.get({userId: 123}).$promise.then(function(user) {
353
372
  user.abc = true;
354
373
  user.$save();
355
374
  });
356
375
  ```
357
376
  *
358
- * It's worth noting that the success callback for `get`, `query` and other methods gets passed
359
- * in the response that came from the server as well as $http header getter function, so one
360
- * could rewrite the above example and get access to http headers as:
377
+ * It's worth noting that the success callback for `get`, `query` and other methods gets called with
378
+ * the resource instance (populated with the data that came from the server) as well as an `$http`
379
+ * header getter function, the HTTP status code and the response status text. So one could rewrite
380
+ * the above example and get access to HTTP headers as follows:
361
381
  *
362
382
  ```js
363
- var User = $resource('/user/:userId', {userId:'@id'});
364
- User.get({userId:123}, function(user, getResponseHeaders){
383
+ var User = $resource('/users/:userId', {userId: '@id'});
384
+ User.get({userId: 123}, function(user, getResponseHeaders) {
365
385
  user.abc = true;
366
386
  user.$save(function(user, putResponseHeaders) {
367
- //user => saved user object
368
- //putResponseHeaders => $http header getter
387
+ // `user` => saved `User` object
388
+ // `putResponseHeaders` => `$http` header getter
369
389
  });
370
390
  });
371
391
  ```
372
392
  *
373
- * You can also access the raw `$http` promise via the `$promise` property on the object returned
374
- *
375
- ```
376
- var User = $resource('/user/:userId', {userId:'@id'});
377
- User.get({userId:123})
378
- .$promise.then(function(user) {
379
- $scope.user = user;
380
- });
381
- ```
382
- *
383
393
  * @example
384
394
  *
385
- * ### Creating a custom 'PUT' request
395
+ * ### Creating custom actions
386
396
  *
387
- * In this example we create a custom method on our resource to make a PUT request
388
- * ```js
389
- * var app = angular.module('app', ['ngResource', 'ngRoute']);
390
- *
391
- * // Some APIs expect a PUT request in the format URL/object/ID
392
- * // Here we are creating an 'update' method
393
- * app.factory('Notes', ['$resource', function($resource) {
394
- * return $resource('/notes/:id', null,
395
- * {
396
- * 'update': { method:'PUT' }
397
- * });
398
- * }]);
399
- *
400
- * // In our controller we get the ID from the URL using ngRoute and $routeParams
401
- * // We pass in $routeParams and our Notes factory along with $scope
402
- * app.controller('NotesCtrl', ['$scope', '$routeParams', 'Notes',
403
- function($scope, $routeParams, Notes) {
404
- * // First get a note object from the factory
405
- * var note = Notes.get({ id:$routeParams.id });
406
- * $id = note.id;
407
- *
408
- * // Now call update passing in the ID first then the object you are updating
409
- * Notes.update({ id:$id }, note);
410
- *
411
- * // This will PUT /notes/ID with the note object in the request payload
412
- * }]);
413
- * ```
397
+ * In this example we create a custom method on our resource to make a PUT request:
398
+ *
399
+ ```js
400
+ var app = angular.module('app', ['ngResource']);
401
+
402
+ // Some APIs expect a PUT request in the format URL/object/ID
403
+ // Here we are creating an 'update' method
404
+ app.factory('Notes', ['$resource', function($resource) {
405
+ return $resource('/notes/:id', {id: '@id'}, {
406
+ update: {method: 'PUT'}
407
+ });
408
+ }]);
409
+
410
+ // In our controller we get the ID from the URL using `$location`
411
+ app.controller('NotesCtrl', ['$location', 'Notes', function($location, Notes) {
412
+ // First, retrieve the corresponding `Note` object from the server
413
+ // (Assuming a URL of the form `.../notes?id=XYZ`)
414
+ var noteId = $location.search().id;
415
+ var note = Notes.get({id: noteId});
416
+
417
+ note.$promise.then(function() {
418
+ note.content = 'Hello, world!';
419
+
420
+ // Now call `update` to save the changes on the server
421
+ Notes.update(note);
422
+ // This will PUT /notes/ID with the note object as the request payload
423
+
424
+ // Since `update` is a non-GET method, it will also be available on the instance
425
+ // (prefixed with `$`), so we could replace the `Note.update()` call with:
426
+ //note.$update();
427
+ });
428
+ }]);
429
+ ```
414
430
  *
415
431
  * @example
416
432
  *
@@ -421,7 +437,7 @@ function shallowClearAndCopy(src, dst) {
421
437
  *
422
438
  ```js
423
439
  // ...defining the `Hotel` resource...
424
- var Hotel = $resource('/api/hotel/:id', {id: '@id'}, {
440
+ var Hotel = $resource('/api/hotels/:id', {id: '@id'}, {
425
441
  // Let's make the `query()` method cancellable
426
442
  query: {method: 'get', isArray: true, cancellable: true}
427
443
  });
@@ -431,17 +447,57 @@ function shallowClearAndCopy(src, dst) {
431
447
  this.onDestinationChanged = function onDestinationChanged(destination) {
432
448
  // We don't care about any pending request for hotels
433
449
  // in a different destination any more
434
- this.availableHotels.$cancelRequest();
450
+ if (this.availableHotels) {
451
+ this.availableHotels.$cancelRequest();
452
+ }
435
453
 
436
- // Let's query for hotels in '<destination>'
437
- // (calls: /api/hotel?location=<destination>)
454
+ // Let's query for hotels in `destination`
455
+ // (calls: /api/hotels?location=<destination>)
438
456
  this.availableHotels = Hotel.query({location: destination});
439
457
  };
440
458
  ```
441
459
  *
460
+ * @example
461
+ *
462
+ * ### Using interceptors
463
+ *
464
+ * You can use interceptors to transform the request or response, perform additional operations, and
465
+ * modify the returned instance/collection. The following example, uses `request` and `response`
466
+ * interceptors to augment the returned instance with additional info:
467
+ *
468
+ ```js
469
+ var Thing = $resource('/api/things/:id', {id: '@id'}, {
470
+ save: {
471
+ method: 'POST',
472
+ interceptor: {
473
+ request: function(config) {
474
+ // Before the request is sent out, store a timestamp on the request config
475
+ config.requestTimestamp = Date.now();
476
+ return config;
477
+ },
478
+ response: function(response) {
479
+ // Get the instance from the response object
480
+ var instance = response.resource;
481
+
482
+ // Augment the instance with a custom `saveLatency` property, computed as the time
483
+ // between sending the request and receiving the response.
484
+ instance.saveLatency = Date.now() - response.config.requestTimestamp;
485
+
486
+ // Return the instance
487
+ return instance;
488
+ }
489
+ }
490
+ }
491
+ });
492
+
493
+ Thing.save({foo: 'bar'}).$promise.then(function(thing) {
494
+ console.log('That thing was saved in ' + thing.saveLatency + 'ms.');
495
+ });
496
+ ```
497
+ *
442
498
  */
443
499
  angular.module('ngResource', ['ng']).
444
- info({ angularVersion: '1.6.8' }).
500
+ info({ angularVersion: '1.8.0' }).
445
501
  provider('$resource', function ResourceProvider() {
446
502
  var PROTOCOL_AND_IPV6_REGEX = /^https?:\/\/\[[^\]]*][^/]*/;
447
503
 
@@ -671,34 +727,34 @@ angular.module('ngResource', ['ng']).
671
727
  }
672
728
 
673
729
  Resource[name] = function(a1, a2, a3, a4) {
674
- var params = {}, data, success, error;
730
+ var params = {}, data, onSuccess, onError;
675
731
 
676
732
  switch (arguments.length) {
677
733
  case 4:
678
- error = a4;
679
- success = a3;
734
+ onError = a4;
735
+ onSuccess = a3;
680
736
  // falls through
681
737
  case 3:
682
738
  case 2:
683
739
  if (isFunction(a2)) {
684
740
  if (isFunction(a1)) {
685
- success = a1;
686
- error = a2;
741
+ onSuccess = a1;
742
+ onError = a2;
687
743
  break;
688
744
  }
689
745
 
690
- success = a2;
691
- error = a3;
746
+ onSuccess = a2;
747
+ onError = a3;
692
748
  // falls through
693
749
  } else {
694
750
  params = a1;
695
751
  data = a2;
696
- success = a3;
752
+ onSuccess = a3;
697
753
  break;
698
754
  }
699
755
  // falls through
700
756
  case 1:
701
- if (isFunction(a1)) success = a1;
757
+ if (isFunction(a1)) onSuccess = a1;
702
758
  else if (hasBody) data = a1;
703
759
  else params = a1;
704
760
  break;
@@ -712,14 +768,20 @@ angular.module('ngResource', ['ng']).
712
768
  var isInstanceCall = this instanceof Resource;
713
769
  var value = isInstanceCall ? data : (action.isArray ? [] : new Resource(data));
714
770
  var httpConfig = {};
771
+ var requestInterceptor = action.interceptor && action.interceptor.request || undefined;
772
+ var requestErrorInterceptor = action.interceptor && action.interceptor.requestError ||
773
+ undefined;
715
774
  var responseInterceptor = action.interceptor && action.interceptor.response ||
716
775
  defaultResponseInterceptor;
717
776
  var responseErrorInterceptor = action.interceptor && action.interceptor.responseError ||
718
- undefined;
719
- var hasError = !!error;
720
- var hasResponseErrorInterceptor = !!responseErrorInterceptor;
777
+ $q.reject;
778
+ var successCallback = onSuccess ? function(val) {
779
+ onSuccess(val, response.headers, response.status, response.statusText);
780
+ } : undefined;
781
+ var errorCallback = onError || undefined;
721
782
  var timeoutDeferred;
722
783
  var numericTimeoutPromise;
784
+ var response;
723
785
 
724
786
  forEach(action, function(value, key) {
725
787
  switch (key) {
@@ -748,8 +810,15 @@ angular.module('ngResource', ['ng']).
748
810
  extend({}, extractParams(data, action.params || {}), params),
749
811
  action.url);
750
812
 
751
- var promise = $http(httpConfig).then(function(response) {
752
- var data = response.data;
813
+ // Start the promise chain
814
+ var promise = $q.
815
+ resolve(httpConfig).
816
+ then(requestInterceptor).
817
+ catch(requestErrorInterceptor).
818
+ then($http);
819
+
820
+ promise = promise.then(function(resp) {
821
+ var data = resp.data;
753
822
 
754
823
  if (data) {
755
824
  // Need to convert action.isArray to boolean in case it is undefined
@@ -777,12 +846,14 @@ angular.module('ngResource', ['ng']).
777
846
  value.$promise = promise; // Restore the promise
778
847
  }
779
848
  }
780
- response.resource = value;
781
849
 
782
- return response;
783
- }, function(response) {
784
- response.resource = value;
785
- return $q.reject(response);
850
+ resp.resource = value;
851
+ response = resp;
852
+ return responseInterceptor(resp);
853
+ }, function(rejectionOrResponse) {
854
+ rejectionOrResponse.resource = value;
855
+ response = rejectionOrResponse;
856
+ return responseErrorInterceptor(rejectionOrResponse);
786
857
  });
787
858
 
788
859
  promise = promise['finally'](function() {
@@ -794,25 +865,8 @@ angular.module('ngResource', ['ng']).
794
865
  }
795
866
  });
796
867
 
797
- promise = promise.then(
798
- function(response) {
799
- var value = responseInterceptor(response);
800
- (success || noop)(value, response.headers, response.status, response.statusText);
801
- return value;
802
- },
803
- (hasError || hasResponseErrorInterceptor) ?
804
- function(response) {
805
- if (hasError && !hasResponseErrorInterceptor) {
806
- // Avoid `Possibly Unhandled Rejection` error,
807
- // but still fulfill the returned promise with a rejection
808
- promise.catch(noop);
809
- }
810
- if (hasError) error(response);
811
- return hasResponseErrorInterceptor ?
812
- responseErrorInterceptor(response) :
813
- $q.reject(response);
814
- } :
815
- undefined);
868
+ // Run the `success`/`error` callbacks, but do not let them affect the returned promise.
869
+ promise.then(successCallback, errorCallback);
816
870
 
817
871
  if (!isInstanceCall) {
818
872
  // we are creating instance / collection