AngularJS $resource parameter is not replaced with its real value? - javascript

I have recently decided to use $resource for REST service, but I quickly got in trouble. I have a simple URL:
/r/interface/activate/:active/addr/:address
But calling it in unit test make it fail with:
// expected: POST /r/interface/activate/false/addr/123
// got : POST /r/interface/activate/false/addr/#address
My defined resource is :
module.factory('NetworkInterfaceActivationService', function ($resource) {
return $resource("/r/interface/activate/:active/addr/:address", {}, {
activate:{method:'POST', params:{active:"true", address:'#address'}, isArray:false},
deactivate:{method:'POST', params:{active:"false", address:'#address'}, isArray:false}
});
});
And this is how I call my service !
$scope.deactivateNetworkAddress = function (address) {
NetworkInterfaceActivationService.deactivate({address:address});
};
Am I missing something?

I tried your code with Angular 1.3, but I couldn't reproduce the problem.
jsFiddle
<button ng-click="parentCtrl.doIt('123foobar')">execute</button>
app.controller('ParentCtrl', function (NetworkInterfaceActivationService) {
this.doIt = function (address) {
NetworkInterfaceActivationService.deactivate({address:address});
};
})
app.factory('NetworkInterfaceActivationService', function ($resource) {
return $resource("/r/interface/activate/:active/addr/:address", {}, {
activate:{method:'POST', params:{active:"true", address:'#address'}, isArray:false}
});
});
HTTP call in console:
POST .../r/interface/activate/false/addr/123foobar

Related

Using service, ngResource save

I'm new to Angular.
I have this Service(?) for my RESTful services.
.factory('LanguagesService', function ($resource) {
return $resource('http://127.0.0.1:8000/language/:langId', {
langId: '#id'
});
});
Then in my controller I do like this
adminLang.addLanguage = function () {
LanguagesService.save({
code: adminLang.newCode,
name: adminLang.newName
});
}
My question is, how do I know if the save() is successful? So I can do this or that depending on if it fails or succeeds?
Thank you a lot.
When you request add two callback functions as below:
LanguagesService.save({
code: adminLang.newCode,
name: adminLang.newName
}, function(response){
// success
}, function(error){
// error
});
Check this for more information: http://fdietz.github.io/recipes-with-angular-js/consuming-external-services/consuming-restful-apis.html
$resource methods returns a promise object via $promise object, you could keep eye on that promise by placing .then.
Code
LanguagesService.save({
code: adminLang.newCode,
name: adminLang.newName
}).$promise.then(function(data){
console.log(data);
//do other awesome things
}, function(err){
});

Recall $resource factory within interception

I have the following factory:
.factory('Request', ['$resource', 'general',
function ($resource) {
return $resource(baseURL + ':resourceName/', {}, {
get : {
method : 'GET',
isArray : true,
transformResponse : function (data, headers) {
return JSON.parse(data).data;
},
interceptor: {
responseError : function (data) {
gnrl.logIn({},false,function(){console.log("test");});
// ???? How to recall this request?
}
}
}
});
}
]);
What I'm trying to do is, if the user has some trouble in this request, the user should login again and the request should be executed again.
The request factory is called as follows:
Request.get(params, headers, function (res) {
//does some operation with results
});
I have seen some related questions but none of them could fit my situation completely.
It is solved using the answers referred in the question. As said, the main idea was using $promise instead of interceptor.
I have solved the problem as follows:
The following is a function in my service
self.doRequest = function(nOfRetries, params, successFunction) {
function fai(a) {
nOfRetries--;
self.logIn(function(){self.doRequest(nOfRetries);});
}
if (nOfRetries >= 0) {
Request.get(params).then(successFunction).catch(fai);
}
}
Login is just another function in the same service and as a callback function i send a request to this function.
doRequest is called as follows:
general.doRequest(3, params/*parameters used in request*/, function (res) {
/***cb function for your initially request*/
});
As last, you see the Request factory:
.factory('Request', ['$resource',
function ($resource) {
var res = $resource(baseURL + ':resourceName/', {}, {
get : {
method : 'GET'
}
});
return {
get : function (arguments) {
return res.get(arguments).$promise;
}
};
}
])
Note that any error (server-side or not) occurred in doRequest's success callback function will also lead to executing failure callback function.

Undefined : value.push(new Resource(item)

I'm trying to test a factory but I'm getting a weird error. I looked around but haven't been able to find a similar problem. Any idea on what I'm doing wrong?
TypeError: 'undefined' is not a function (evaluating 'value.push(new Resource(item))')
Using angluarjs v1.3.20
factory.js
'use strict';
//Business service used for communicating with the articles REST endpoints
angular.module('businesses').factory('Business', ['$resource',
function ($resource) {
return $resource('api/businesses/:businessId', {
businessId: '#_id'
}, {
update: {
method: 'PUT'
}
});
}
]);
test.js
describe('My Service', function () {
// Then we can start by loading the main application module
beforeEach(module(ApplicationConfiguration.applicationModuleName));
afterEach(inject(function($httpBackend){
//These two calls will make sure that at the end of the test, all expected http calls were made
$httpBackend.verifyNoOutstandingExpectation();
$httpBackend.verifyNoOutstandingRequest();
}));
it('mock http call', inject(function($httpBackend, Business) {
var resource = new Business({
_id:'abcd'
});
var arraya = [{
_id:'abcd'
}, {
_id:'abcde'
}];
//Create an expectation for the correct url, and respond with a mock object
$httpBackend.expectGET('api/businesses/abcd').respond(200, arraya)
resource.$query();
//Because we're mocking an async action, ngMock provides a method for us to explicitly flush the request
$httpBackend.flush();
//Now the resource should behave as expected
console.log(resource);
//expect(resource.name).toBe('test');
}));
});
xxxxxxxxxxxxxxxxxxxxxxxxxxx
Shouldn't you only expect after you flushed?
resource.$query();
//Because we're mocking an async action, ngMock provides a method for us to explicitly flush the request
$httpBackend.flush();
//Create an expectation for the correct url, and respond with a mock object
$httpBackend.expectGET('api/businesses/abcd').respond(200, arraya);

Reading data from $resource.get() in AngularJS

JSON/XML from REST
{
litm: "T00000245",
lotn: "00004"
}
<jdeSerials>
<litm>T00000245</litm>
<lotn>00004</lotn>
</jdeSerials>
AngularJS controller
//Searching a product with serial number/LOTN
$scope.searchProduct = function () {
var lotn = $scope.jdeSerials.lotn;
console.log("searchProduct---->" + lotn);//log-->searchProduct---->00004
$scope.JdeSerials = lotnService.get({id: lotn}, function() {
console.log($scope.jdeSerials);//log-->[object Object]
console.log($scope.jdeSerials.litm);//log-->undefined!!!!!
});
//var litm = $scope.jdeSerials.litm;
//$scope.jdeproduct = productService.get({id: litm});
};
AngularJS service
angular.module('lotnService', ['ngResource'])
.factory('lotnService', ['$resource',
function ($resource) {
console.log('------lotmService-----');
return $resource(
'http://localhost:8080/RMAServer/webresources/com.pako.entity.jdeserials/:id',
{},
{
update: { method: 'PUT', params: {id: '#lotn'} }
});
}]);
Question
How can I get a value to $scope.jdeSerials.litm? Is there any better idea to solve this like creating a service which handles this two GETs? I think that reason is the GET method is asynchronous, but what is the best solution to handle situations like this?
EDIT/update
I changed the service call like this:
$scope.JdeSerials = lotnService.get({id:lotn})
.$promise.then(function(jdeSerials) {
$scope.jdeSerials = jdeSerials;
console.log("1--------------->LITM:"+$scope.jdeSerials.litm);
});
I got the LITM, BUT I got the errormessage as well:
TypeError: Cannot read property 'then' of undefined
Try to create a get method in your resource.
angular.module('lotnService', ['ngResource'])
.factory('lotnService', ['$resource', function ($resource) {
return $resource( 'http://localhost:8080/RMAServer/webresources/com.pako.entity.jdeserials/:id',
{},
{
get: { method: 'GET', params: {id: '#lotn'}},
update: { method: 'PUT', params: {id: '#lotn'} }
});
}]);
Then in your controller, call method get from service:
lotnService.get({id:lotn}).$promise.then(
function(jdeSerials) {
$scope.jdeSerials = jdeSerials;
console.log("1--------------->LITM:"+$scope.jdeSerials.litm);
});
What angular js version are you using?
Does the following work ?
lotnService.get({id:lotn}).then(
function(jdeSerials) { ... }
);
(without the $promise)
I was browsing the docs and also angular-resource.js source for previous versions and it appears that the synthax has changed somewhere along the line.
On angular-resource.js 1.2.0 source:
The Resource instances and collection have these additional properties:
$promise: the {#link ng.$q promise} of the
original server interaction that created this * instance or
collection.
On 1.0.8 there is no mention of the $promise propery, however.

AngularJS shows me "digest already in progress" after calling API

I'm using AngularJS resource to call an API. When I get a list of items with the API, all shows well in my ng-grid. When I try to filter on for example employeename, angular returns me "digest already in progress". What could be the problem?
What I did to call the api is this:
'use strict';
angularApp.factory('absenceResource',['$resource',function($resource){
var baseUrl = config.apiurl;
var buildUrl = function(resourceUrl){
return baseUrl + resourceUrl;
};
return $resource(buildUrl('api/absences/:employee'),
{employee: '#employee'},
{
"update": {method: "PUT"}
});
}]);
Then to call that resource:
'use strict';
angularApp.factory('absenceData',function(absenceResource, authService){
return{
getAbsence: function(absenceId){
return absenceResource.query({id: absenceId});
},
getAllAbsences: function(){
return absenceResource.query();
},
getAllAbsencesForUser: function(user){
return absenceResource.query({'employee': user});
},
update: function(absence){
absenceResource.$update(absence);
},
save: function(absence){
absenceResource.save(absence);
}
};
Then in my controller I do this:
$scope.absencesForUser = absenceData.getAllAbsencesForUser("jurgen");
//$scope.absences = absenceData.getAllAbsences();
$scope.gridOptions = {
data: 'absencesForUser'
};
I then get the digest error.
I've searched for this problem, but all the problems that I've found had to do with $rootScope.apply and I don't use that.
Can somebody help me?

Categories

Resources