glock18 glock18 - 1 month ago 17
reST (reStructuredText) Question

Angular ngResource $save Method Clears $response Object

Using Angular 1.5.5 here:

Is there any way to tell Angular to ignore response body for particular requests (such as $save)? It drives me crazy that after I call $save, angular updates the model with the object returned by a server, which initially was supposed to be used to distinguish between different resolutions of the request. It results in unwanted form clear. Interestingly enough, this behaviour remains even if I send a 400 or 500 http status code.

In case you need more info, relevant code is below.

Controller:

'use strict';
angular
.module('app.operators')
.controller('OperatorNewController', OperatorNewController);

OperatorNewController.$inject = ['operatorsService', 'notify'];

function OperatorNewController(operatorsService, notify) {
var vm = this;
vm.done = done;

activate();

function activate() {
vm.operator = new operatorsService();
}

function done(form) {
if (form.$invalid) {
// do stuff
return false;
}

vm.operator.$save(function(response) {
if (response.success && response._id) {
$state.go('app.operators.details', {id: response._id}, { reload: true });
} else if (response.inactive) {
// do stuff
} else {
// do other stuff
}
}, function (error) {
// do other stuff
});
}
}


Service:

'use strict';
angular
.module('app.operators')
.service('operatorsService', operatorsService);

operatorsService.$inject = ['$resource'];

function operatorsService($resource) {
return $resource('/operators/:id/', {id: '@_id'}, {
'update': { method: 'PUT' }
});
}


Server request handler is also fairly simple:

.post('/', function (req, res) {
if (!req.operator.active) {
return res.status(500).json({ inactive: true, success: false });
}
// do stuff
return res.json({ success: true });
});


In either way I don't like the idea of having to send the entire object from server (particularily when it's a failed request), and even if I have to, I still need a way to send some extra data that will be ignored by Angular.

Your help is very much appreciated!

Answer

The $save method of the resource object empties and replaces the object with the results of the XHR POST results. To avoid this, use the .save method of the operatorsService:

  //vm.operator.$save(function(response) {
  vm.newOperator = operatorsService.save(vm.operator, function(response),
    if (response.success && response._id) {
      $state.go('app.operators.details', {id: response._id}, { reload: true });
    } else if (response.inactive) {
      // do stuff
    } else {
      // do other stuff
    }
  }, function (error) {
    // do other stuff
  });

UPDATE

It results in unwanted form clear. Interestingly enough, this behaviour remains even if I send a 400 or 500 http status code.

This behavior is NOT VERIFIED.

I created a PLNKR to attempt to verify this behavior and found that the $save method does not replace the resource object if the server returns a status of 400 or 500. However it does empty and replace the resource object if the XHR status code is 200 (OK).

The DEMO on PLNKR

Comments