I have implemented angular $resource with custom functions and parameters as follows:-
.factory('CandidateService', ['$resource', function ($resource) {
return $resource("api/:action/:id", {},
{
'getCandidates': { method: "GET", params: { action: "Candidate" }, isArray: true },
'getCandidate': { method: 'GET', params: { action: "Candidate", id: "#id" } }
});
}]);
And I am consuming this in the controller as follows:-
.controller('Controller', ['CandidateService', function ($scope, CandidateService) {
$scope.candidateList = [];
CandidateService.getAll(function (data) {
$scope.candidateList = data;
});
}]);
This is working absolutely fine. Now I need to cache the data from the api into the CandidateService Factory so it is not loaded eveytime I move between the controllers.
So I thought i would do something as follows:-
.factory('CandidateService', ['$resource', function ($resource) {
var Api = $resource("api/:action/:id", {},
{
'getCandidates': { method: "GET", params: { action: "Candidate" }, isArray: true },
'getCandidate': { method: 'GET', params: { action: "Candidate", id: "#id" } }
});
var candidateDataLoaded = false;
var candidateData = [];
return {
getCandidates: function () {
if (!candidateDataLoaded) {
Api.getAll(function (data) {
angular.copy(data, candidateData);
});
}
return candidateData;
}
}
}]);
But I just cant get this to work. I think it has something to do with angular factory being a singleton.
Is my approach correct to implement the caching?
You can use the $cacheFactory object.
See : http://docs.angularjs.org/api/ng.$cacheFactory
You can cache $http request like that :
var $httpDefaultCache = $cacheFactory.get('$http');
If you want to retrieve a specific url in cache do :
var cachedData = $httpDefaultCache.get('http://myserver.com/foo/bar/123');
$You can clear the cache too :
$httpDefaultCache.remove('http://myserver.com/foo/bar/123');
or :
$httpDefaultCache.removeAll();
Complete post here : Power up $http with caching
Related
I'm a beginner in Angular world, and I can't work out why I'm still getting "not defined" error. Here is my code:
angular.module('dopasujApp').factory('getProducts', ['$http', function ($http) {
var dataFactory = {};
dataFactory.sort='ASC';
dataFactory.orderBy='PRODUCT_NAME';
dataFactory.search='a';
dataFactory.filters={};
dataFactory.filters.ATTRIBS=[46,25];
dataFactory.filters.SIZE=[165,40];
getProducts.listProducts = function() {
var request = $http({
method: "POST",
url: "http://******/backend/internalAPI.php?action=getListing&fit=1&limit=10&vendor=20",
headers: {
'Content-Type': 'application/json'
},
data: {
data: dataFactory
}
});
var products = angular.fromJson(request);
return products;
}
return false;
}]);
And here goes my controller (just for testing purposes now).
angular.module('dopasujApp')
.controller('MainCtrl', ['getProducts', '$scope','$rootScope',
function (getProducts, $scope,$rootScope) {
console.log(getProducts.listProducts())
}
]);
getProducts variable in factory is not defined. The name you used before is just informative name for angular
In your factory you are returning "false" as actual result. So angular treats your "false" as result.
It should look like that :
angular.module('dopasujApp').factory('getProducts', ['$http', function ($http) {
var dataFactory = {}, getProducts = {};
dataFactory.sort='ASC';
dataFactory.orderBy='PRODUCT_NAME';
dataFactory.search='a';
dataFactory.filters={};
dataFactory.filters.ATTRIBS=[46,25];
dataFactory.filters.SIZE=[165,40];
getProducts.listProducts = function() {
return $http({
method: "POST",
url: "http://******/backend/internalAPI.php?action=getListing&fit=1&limit=10&vendor=20",
headers: {
'Content-Type': 'application/json'
},
data: {
data: dataFactory
}
});
}
return getProducts;
}]);
Controller
angular.module('dopasujApp').controller('MainCtrl', ['getProducts', '$scope','$rootScope',
function (getProducts, $scope,$rootScope) {
getProducts.listProducts().then(function(res) {
console.log(res.data);
});
}
]);
EDIT:
Also note, that $http returns promise, but not actual query result, updated my example accordingly
try like this
var yourapp = angular.module('dopasujApp', []); //your defining your app first
yourapp.factory('getProducts', function ($http)
{
return {
//write your factory methods
};
});
you controller should be like below
yourapp.controller('MainCtrl', function PostController($scope, getProducts, $compile)
{
//here your controller methods
});
I am passing an object to angular factory it is throwing error.
factory:
visitorApp.factory('loginRepository', function ($resource) {
return {
VerifyVisitor: $resource('/api/VisitorWeb/VerifyLogin', {}, {
query: { method: 'POST', params: {loginModel:loginModel}, isArray: true }
})
};
});
The complex object i am trying to pass is loginModel.
From controller call to factory.
visitorApp.controller('LoginController', function ($scope,$location,$route,loginRepository) {
$scope.submit = function (isValid) {
if (isValid) {
var loginModel = {
UserName: $scope.UserName,
PassWord: $scope.Password
};
var response = loginRepository.VerifyVisitor.query(loginModel);
alert(response);
}
}
});
Error: loginModel is not defined
Web Api Method which is being called.
[HttpPost]
public string VerifyLogin(UserLoginDomainModel loginModel)
{
var msg = _loginService.Login(loginModel);
return msg;
}
Is it the right way of using $resource to post a request and pass complex object.
Your service should look something like this:
visitorApp.factory('loginRepository', function ($resource) {
return {
VerifyVisitor: $resource('/api/VisitorWeb/VerifyLogin', {},
{
query: {
method: 'POST',
params: {loginModel: '#loginModel'},
isArray: true }
})
};
});
The parameter variables are enclosed in quotes and prefixed with an #.
is this possible with AngularJS Resource?
/api/client/:id/jobs (get all the jobs from this client)
/api/client/:id/job/:jobId (get the job form this client)
My Factory:
.factory('Client', ['$resource', 'Api',
function ($resource, Api) {
var Client = $resource(Api.url() + 'client/:id/',
{
id: '#id'
},
{
'update' : { method: 'PUT', isArray: false }
}
);
return Client;
}
]);
Thanks!
I found a solution for my problem.
I have to create another factory to do the job:
.factory('ClientJobs', ['$resource', 'Api',
function ($resource, Api) {
var ClientJobs = $resource(Api.url() + 'client/:clientId/job/:jobId',
{
clientId: '#Id',
jobId: '#Id'
},
{
'query': { method: 'GET', isArray: true },
'update': { method: 'PUT' }
}
);
return ClientJobs;
}
]);
And, i can use the factory like this:
ClientJobs.save({clientId:clientId, jobId:job.id}, job, function (result) {
deferred.resolve(result);
}, function (reason) {
deferred.reject(reason);
});
Now, everything is working.
And for help those people who are working with UI-ROUTER, there is this question with an excellent answer about complex states like mine and nested views:
Nested Views with Nested States
I am trying to decorate the returned data from a angular $resource with data from a custom service.
My code is:
angular.module('yoApp')
.service('ServerStatus', ['$resource', 'ServerConfig', function($resource, ServerConfig) {
var mixinConfig = function(data, ServerConfig) {
for ( var i = 0; i < data.servers.length; i++) {
var cfg = ServerConfig.get({server: data.servers[i].name});
if (cfg) {
data.servers[i].cfg = cfg;
}
}
return data;
};
return $resource('/service/server/:server', {server: '#server'}, {
query: {
method: 'GET',
isArray: true,
transformResponse: function(data, header) {
return mixinConfig(angular.fromJson(data), ServerConfig);
}
},
get: {
method: 'GET',
isArray: false,
transformResponse: function(data, header) {
var cfg = ServerConfig.get({server: 'localhost'});
return mixinConfig(angular.fromJson(data), ServerConfig);
}
}
});
}]);
It seems I am doing something wrong concerning dependency injection. The data returned from the ServerConfig.get() is marked as unresolved.
I got this working in a controller where I do the transformation with
ServerStatus.get(function(data) {$scope.mixinConfig(data);});
But I would rather do the decoration in the service. How can I make this work?
It is not possible to use the transformResponse to decorate the data with data from an asynchronous service.
I posted the solution to http://jsfiddle.net/maddin/7zgz6/.
Here is the pseudo-code explaining the solution:
angular.module('myApp').service('MyService', function($q, $resource) {
var getResult = function() {
var fullResult = $q.defer();
$resource('url').get().$promise.then(function(data) {
var partialPromises = [];
for (var i = 0; i < data.elements.length; i++) {
var ires = $q.defer();
partialPromisses.push(ires);
$resource('url2').get().$promise.then(function(data2) {
//do whatever you want with data
ires.resolve(data2);
});
$q.all(partialPromisses).then(function() {
fullResult.resolve(data);
});
return fullResult.promise; // or just fullResult
}
});
};
return {
getResult: getResult
};
});
Well, Its actually possible to decorate the data for a resource asynchronously but not with the transformResponse method. An interceptor should be used.
Here's a quick sample.
angular.module('app').factory('myResource', function ($resource, $http) {
return $resource('api/myresource', {}, {
get: {
method: 'GET',
interceptor: {
response: function (response) {
var originalData = response.data;
return $http({
method: 'GET',
url: 'api/otherresource'
})
.then(function (response) {
//modify the data of myResource with the data from the second request
originalData.otherResource = response.data;
return originalData;
});
}
}
});
You can use any service/resource instead of $http.
Update:
Due to the way angular's $resource interceptor is implemented the code above will only decorate the data returned by the $promise and in a way breaks some of the $resource concepts, this in particular.
var myObject = myResource.get(myId);
Only this will work.
var myObject;
myResource.get(myId).$promise.then(function (res) {
myObject = res;
});
I can't catch request on ASP.NET MVC project on server side controller from AngularJS:
var appDirective = angular.module('app.directive', []);
var xmplService = angular.module('app.service', ['ngResource']);
var appFilter = angular.module('app.filter', []);
var app = angular.module('app', ['app.service', 'app.directive', 'app.filter', 'solo.table']);
xmplService
.factory('testResource1', function ($resource) {
return $resource('/SoloAngularTable/TestMethod3', { id: '#id' }, { charge: { method: 'POST' } });
});
app
.controller('ContentPlaceHolder1Controller', function ($scope, $http, testResource1) {
testResource1.find({ id: 123 }, function (data) {
alert('success');
});
});
On MVC Controller I have a method that can't catch request:
[HttpPost]
public JsonResult TestMethod3(int id)
{
var data = new { User = "Alex" };
return Json(data);
}
How to build simple request to server side with AngularJS $resource and catch request?
find is not a default action for $resource. The defaults are:
{ 'get': {method:'GET'},
'save': {method:'POST'},
'query': {method:'GET', isArray:true},
'remove': {method:'DELETE'},
'delete': {method:'DELETE'} };
You will have to create/specify the find action. You are currently creating/specifying a charge action. Perhaps this is what you meant to use?
If you want to use find, here is the fix:
.factory('testResource1', function ($resource) {
return $resource('/SoloAngularTable/TestMethod3', { id: '#id' }, {
charge: { method: 'POST' },
find: { method: 'POST' } // Added `find` action
});
});
If you meant to use charge, here is the fix:
.controller('ContentPlaceHolder1Controller', function ($scope, $http, testResource1) {
testResource1.charge({ id: 123 }, function (data) {
alert('success');
});
});