I have an angular service based on meanjs for rents. Originally it looked like this:
(function () {
'use strict';
angular
.module('rents.services')
.factory('RentsService', RentsService);
RentsService.$inject = ['$resource', '$log'];
function RentsService($resource, $log) {
var Rent = $resource(
'/api/rents/:rentId',
{
rentId: '#_id'
},
{
update: {
method: 'PUT'
},
getByCarId:
{
method: 'POST',
params: {
rentId: 'bycar'
},
isArray: true,
hasBody: true,
requestType: 'json',
responseType: 'json'
}
}
);
angular.extend(Rent.prototype, {
createOrUpdate: function () {
var rent = this;
return createOrUpdate(rent);
}
});
return Rent;
// and all other function that are the same as down below
}());
Then I added a second resource
(function () {
'use strict';
angular
.module('rents.services')
.factory('RentsService', RentsService);
RentsService.$inject = ['$resource', '$log'];
function RentsService($resource, $log) {
var Rent =
{
basic: $resource(
'/api/rents/:rentId',
{
rentId: '#_id'
},
{
update: {
method: 'PUT'
},
getByCarId:
{
method: 'POST',
params: {
rentId: 'bycar'
},
isArray: true,
hasBody: true,
requestType: 'json',
responseType: 'json'
}
}
),
carUsageStats: $resource(
'/api/rents/car_usage'
)
};
angular.extend(Rent.basic.prototype, {
createOrUpdate: function () {
var rent = this;
return createOrUpdate(rent);
}
});
return Rent;
function createOrUpdate(rent) {
if (rent._id) {
return rent.$update(onSuccess, onError);
} else {
return rent.$save(onSuccess, onError);
}
// Handle successful response
function onSuccess(rent) {
// Any required internal processing from inside the service, goes here.
}
// Handle error response
function onError(errorResponse) {
var error = errorResponse.data;
// Handle error internally
handleError(error);
}
}
function handleError(error) {
// Log error
$log.error(error);
}
}
}());
Until I added second resource, this resolve function for creating new rent worked fine
newRent.$inject = ['RentsService'];
function newRent(RentsService) {
return new RentsService();
}
But when I added second resource (and had to address the one I want by using property name - cant use Rent.query() but Rent.basic.query()) instantiating new Rent no longer works. I added console log outputs around and code stops executing at line var rent = new RentsService(). Querying works fine. What is the correct way of making new object using service with multiple resources?
Related
I am trying to make an update to an existing object but get the following error $scope.entry.update is not a function.
I created a service called 'budgetResource'
"use strict";
angular.module("common.services").factory("budgetResource", ["$resource", "appSettings", budgetResource])
function budgetResource($resource, appSettings) {
return $resource(appSettings.serverPath + "api/budget/:id", null,
{
'update': { method: 'PUT', isArray: true },
'delete': { method: 'DELETE', isArray: true },
'save': { method: 'POST', isArray: true }
});
}
Herewith the function in my controller where budgetResource service is injected with the function $scope.updateBudgetAmount being called.
$scope.updateBudgetAmount = function (categoryId) {
$scope.entry = new budgetResource();
$scope.entry = {
"budgetAmount": $scope.budgetAmount,
"categoryId": categoryId
}
$scope.entry.update({ id: categoryId },
function (data) {
$scope.categories = data;
$scope.category = "";
},
function (error) {
$scope.message = error.statusText;
});
}
which in turn calls the webapi method
public IHttpActionResult Put(int id, [FromBody]Category cat)
{
try
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
BudgetRepository repo = new BudgetRepository();
var categories = repo.SaveCategory(cat);
return Ok(categories);
}
How can modify this so that it is dine correctly?
After you do $scope.entry = {...},$scope.entry becomes a plain javascript object, so $scope.entry.update is not exist.
I have this service :
(function() {
'use strict';
angular
.module('myApp')
.factory('Consultant', Consultant);
Consultant.$inject = ['$resource', 'DateUtils'];
function Consultant ($resource, DateUtils) {
var resourceUrl = 'api/consultants/:id';
return $resource(resourceUrl, {}, {
'query': { method: 'GET', isArray: true},
'get': {
method: 'GET',
transformResponse: function (data) {
data = angular.fromJson(data);
return data;
}
},
'update': {
method: 'PUT',
transformRequest: function (data) {
return angular.toJson(data);
},
transformResponse: function (data) {
data = angular.fromJson(data);
return data;
}
},
'save': {
method: 'POST',
transformRequest: function (data) {
return angular.toJson(data);
},
transformResponse: function (data) {
data = angular.fromJson(data);
return data;
}
}
});
}
})();
What if I want to add the url api/consultantscustom/:id (with its query/get/update methods) to this service?
As it seems that this file can contain only one factory, is there a way to do that or do I need to create another file with a new factory?
Maybe I am totally misunderstanding what you are asking, but you can have as many factories in one file as you like (or as seems useful):
(function() {
'use strict';
angular.module('myApp')
.factory('Consultant', Consultant)
.factory('Custom', Custom);
Consultant.$inject = ['$resource', 'DateUtils'];
Custom.$inject = ['$resource'];
function Consultant ($resource, DateUtils) {
var resourceUrl = 'api/consultants/:id';
...
}
function Custom ($resource) {
var resourceUrl = 'api/consultantscustom/:id';
...
}
Or, if you want to re-use the same factory to access different URLs, you could add methods to set the URL and then re-use the call to the generic resource.
function Consultant ($resource, DateUtils) {
function consultants () {
_call_resource('api/consultants/:id');
}
function custom () {
_call_resource('api/consultantscustom/:id');
}
function _call_resource (resourceUrl) {
return $resource(resourceUrl, {}, {
...
}
}
this.consultants = consultants;
this.custom = custom;
return this;
}
I intend to return few resource from a factory, but unfortunately it failed in my case. It shows the error message Entry is not a function Scope.$scope.create.
This is working code with one resource:
angular.module('Entry').factory('Entry', function($resource) {
return $resource('/api/entries/:id', { id: '#_id' }, {
update: {
method: 'PUT'
}
});
});
$scope.create = function() {
var entry = new Entry({
});
entry.$save(function() {});
}
This is not working code after adding multiple resource:
angular.module('Entry').factory('Entry', function($resource) {
return {
'EntryA': $resource('/api/entries/:id', { id: '#_id' }, {
update: {
method: 'PUT'
}
}),
'EntryB': $resource('/api/entries/:id', { id: '#_id' }, {
update: {
method: 'PUT'
}
}),
};
});
$scope.create = function() {
var entry = new Entry({
});
entry.EntryA.$save(function() {});
}
I have this code in my post.serv.js and in my controller I want to execute the function delete.
"use strict";
app.factory('JnttPost', function ($resource) {
var PostResource = $resource('/api/post/:_id', {
_id: "#id"
}, {
update: {
method: 'PUT',
isArray: false
}
}, {
delete: {
method: 'DELETE',
isArray: false
}
});
return PostResource;
});
I already know how to get and update a post, for example in my createpost.serv.js
"use stric";
app.factory('JnttCreatePost', function ($http, $q, JnttPost) {
return {
createPost: function (newPostData) {
var newPost = new JnttPost(newPostData);
var dfd = $q.defer();
newPost.$save().then(function () {
dfd.resolve();
}, function (response) {
dfd.reject(response.data.reason);
});
return dfd.promise;
}
};
});
and in my newpost.ctrl.js
"use strict";
app.controller('CtrlNewPost',
function ($scope, $location, JnttIdentity, JnttNotifier, JnttCreatePost) {
var email = ...;
$scope.newPost = function () {
var newPostData = {...};
JnttCreatePost.createPost(newPostData).then(function () {
JnttNotifier.notify('success', 'The post has been created');
$location.path('/');
}, function (reason) {
JnttNotifier.notify('error', reason);
});
};
});
I can't realize how to perform the delete request, I can do with a $http
In my new controller for do deletePost() function I have this:
$scope.deletePost = function () {
var pwd = JnttIdentity.currentUser.hashed_pwd;
var postidd = {
password: pwd,
id: $scope.post._id
};
var config = {
method: "DELETE",
url: '/api/post/',
data: postidd,
headers: {
"Content-Type": "application/json;charset=utf-8"
}
};
$http(config);
$location.path('/');
};
This actually already do this stuff but I want to do this without the $http like the create request, How I can do this? How do I can edit this code below for do the request?
createPost: function (newPostData) {
var newPost = new JnttPost(newPostData);
var dfd = $q.defer();
newPost.$save().then(function () {
dfd.resolve();
}, function (response) {
dfd.reject(response.data.reason);
});
return dfd.promise;
}
In my routes.js in express I have this route:
app.delete('/api/post/', posts.deletePost);
You can either call delete on the $resource class you create (JnttPost) or call $delete on a post that's returned from the $resource class.
The $resource class already has get/save/query/remove/delete functions included so you don't need to add the delete (save is create/POST, so you need to include update with PUT).
Here's a sample of using your $resource class to call delete:
angular.module('test', ['ngResource'])
.factory('JnttPost', function ($resource) {
var PostResource = $resource('/api/post/:_id', {
_id: "#id"
}, {
update: {
method: 'PUT',
isArray: false
}
});
return PostResource;
})
.run(function(JnttPost){
JnttPost.delete({id: 123123123});
});
Ok, so I have this service that is dependent on another service value that the user can change in the app interface. Something like this:
app.service('Applications', ['$resource', 'URL',
function ($resource, URL) {
var applicationsResource = $resource(URL + '/applications/:id', { id: '#id' }, {
query: {
method: 'GET',
isArray: true,
transformResponse: function(body, header) {
var response = angular.fromJson(body);
return response.data.applications;
}
}
});
var applications = applicationsResource.query(function() {
applications.current = applications[0];
});
return applications;
}
]);
app.service('Users', ['$resource', 'URL', 'Applications',
function ($resource, URL, Applications) {
return $resource(URL + '/users/:id', { id: '#id' }, {
query: {
method: 'GET',
isArray: true,
headers: {
'User': Applications.current.username,
'Pass': Applications.current.password
},
transformResponse: function(body, header) {
var response = angular.fromJson(body);
return response.data.users;
}
}
});
}
]);
Example of working controller code:
app.controller('usersController', ['$scope', '$resource', 'URL', 'Applications',
function ($scope, $resource, URL, Applications) {
$scope.users = [];
$scope.reload = function() {
$scope.loading = true;
var usersResource = $resource(URL + '/users/:id', { id: '#id' }, {
query: {
method: 'GET',
isArray: true,
headers: {
'User': Applications.current.username,
'Pass': Applications.current.password
},
transformResponse: function(body, header) {
var response = angular.fromJson(body);
return response.data.users;
}
}
});
$scope.users = usersResource.query(function() {
$scope.loading = false;
});
/*
// after injecting Users, this is what I want to do, instead of what's above
$scope.users = Users.query(function() {
$scope.userTable.reload();
$scope.loading = false;
});
*/
};
$scope.$watch('Applications.current', function (newApplication, oldApplication, scope) {
if (newApplication && newApplication !== oldApplication) {
scope.reload();
}
});
}
]);
I want to replace that usersResource with my Users service, but that's where I'm stuck now.
The issue is that no matter what I do, the Applications.current on the Users service is always null. (I only make use of this service after making sure that Applications.current is not null on the controller)
If I move the resource directly to the controller, it works, but I want to move these away from the controllers.
Any tips on how to fix or improve this?
You should know that $resource is async and you call Users service before actually you got response from server and populated applications.current. This a reason why Applications.current is null into Users service.
In your case I would use Uses service into Applications:
app.service('Applications', ['$resource', 'URL', 'Users',
function ($resource, URL, Users) {
var applicationsResource = $resource(URL + '/applications/:id', { id: '#id' }, {
query: {
method: 'GET',
isArray: true,
transformResponse: function(body, header) {
var response = angular.fromJson(body);
return response.data.applications;
}
}
});
var applications = applicationsResource.query(function() {
applications.current = applications[0];
// call the Users
Users.query(applications.current) /**/
return /* ... */;
});
return applications;
}
]);