angular $http.put() works but $http({method: 'PUT'}) does not - angularjs

I am trying to consolidate all my services which make api calls to the Rails back end into one. Here's what it looks like:
angular.module('feeSuitesApp')
.factory('FeeSuitesSvc', [
'$http',
function ($http) {
var TransformInstance, Result;
TransformInstance = function(FeeObj, obj){
return new FeeObj(obj);
};
Result = function(feeSuiteObj){
var servicePlural = feeSuiteObj.service + 's';
return $http({
method: feeSuiteObj.method,
url: feeSuiteObj.url,
params: feeSuiteObj.params,
transformResponse: function(data){
var w = angular.fromJson(data);
angular.forEach(w[servicePlural], function(obj, idx){
w[servicePlural][idx] = TransformInstance(feeSuiteObj.feeObj, obj);
});
return w;
}
})
}
return {
promise: Result,
};
}]);
POST and GET work fine, but PUT gives me a RangeError: Maximum call stack size exceeded
FeeRule looks like this:
angular.module('feeSuitesApp')
.factory('FeeRule', function(){
//constructor
var FeeRule = function(obj){
this.id = obj.id || null;
this.name = obj.name || '';
this.fee_suite_id = obj.fee_suite_id || null;
this.fee_parameter_id = obj.fee_parameter_id || null;
this.multiplier = obj.multiplier || 1;
this.addend = obj.addend || 0;
};
return FeeRule;
});
however, if I make the following call everything works perfectly:
var url = '/api/v3/fee_rules/' + feeRule.id;
$http.put(url, { fee_rule: feeRule});
but if I use my service like this I get the stack overflow error:
var feeSuiteObj = {
url: '/api/v3/fee_rules/' + feeRule.id,
service: 'fee_rule',
method: 'PUT',
params: {
fee_rule: feeRule
},
feeObj: FeeRule
};
FeeSuitesSvc.promise(feeSuiteObj).then(function(success){
$state.go('root');
},function(error){
console.log(error);
});

see https://docs.angularjs.org/api/ng/service/$http#usage, there is no service nor feeObj config properties, also params is used to append serialized data to GET requests (not PUT). So try this:
var feeSuiteObj = {
url: '/api/v3/fee_rules/' + feeRule.id,
method: 'PUT',
data: {
fee_rule: feeRule
}
};
if you need to pass service or feeObj, you can do it within data object:
data: {
fee_rule: feeRule,
service: 'fee_rule',
feeObj: FeeRule
}

Related

Fetch params from URL using app controller

How to pass the multiple parameters to a function using this code? I am able to pass only Username as single parameter but MarkDate is not passing to URL.
var app = angular.module("myModule", ['angularUtils.directives.dirPagination']);
//This Gets all the Pre Clients
app.controller("GetAttendance", function ($scope, $http) {
window.params = function () {
var params = {};
var param_array = window.location.href.split('?')[1].split('&');
for (var i in param_array) {
x = param_array[i].split('=');
params[x[0]] = x[1];
}
return params;
} ();
$http({
url: "../assets/services/MasterWebService.asmx/spGetAttendanceByUsernameDate",
method: "GET",
**params: { Username: window.params.Username , MarkDate : params.Markdate}**
}).then(function (response) {
console.log(response.data);
$scope.GetAttendanceData = response.data;
$scope.TotalOrders = response.data.length;
});
Your "MarkDate" param is not getting its value from the window.params object as you do with "Username". This should work:
$http({
url: "../assets/services/MasterWebService.asmx/spGetAttendanceByUsernameDate",
method: "GET",
**params: { Username: window.params.Username , MarkDate : window.params.Markdate}**
}).then(function (response) {
console.log(response.data);
$scope.GetAttendanceData = response.data;
$scope.TotalOrders = response.data.length;
});

Custom method in an Angular service using $resource in Jhipster

I don't understand the syntax to write a custom method in an Angular Service using $resource in Jhipster. After a lot of research, I am doubtful whether it's even possible.
Here is the code for Angular Service.
(function() {
'use strict';
angular
.module('tealboxApp')
.factory('Task', Task);
Task.$inject = ['$resource', 'DateUtils'];
function Task ($resource, DateUtils) {
var resourceUrl = 'api/tasks/:id';
return $resource(resourceUrl, {}, {
'query': { method: 'GET', isArray: true},
'get': {
method: 'GET',
transformResponse: function (data) {
if (data) {
data = angular.fromJson(data);
data.assignedDateTime = DateUtils.convertDateTimeFromServer(data.assignedDateTime);
data.startDateTime = DateUtils.convertDateTimeFromServer(data.startDateTime);
data.endDateTime = DateUtils.convertDateTimeFromServer(data.endDateTime);
data.startDate = DateUtils.convertLocalDateFromServer(data.startDate);
data.endDate = DateUtils.convertLocalDateFromServer(data.endDate);
}
return data;
}
},
'update': {
method: 'PUT',
transformRequest: function (data) {
var copy = angular.copy(data);
copy.startDate = DateUtils.convertLocalDateToServer(copy.startDate);
copy.endDate = DateUtils.convertLocalDateToServer(copy.endDate);
return angular.toJson(copy);
}
},
'save': {
method: 'POST',
transformRequest: function (data) {
var copy = angular.copy(data);
copy.startDate = DateUtils.convertLocalDateToServer(copy.startDate);
copy.endDate = DateUtils.convertLocalDateToServer(copy.endDate);
return angular.toJson(copy);
}
}
});
}
})();
I want to add a custom method like...
'getTasksWithXYZ': {
method: 'GET',
transformResponse: function (data) {
if (data) {
data = angular.fromJson(data);
data.assignedDateTime = DateUtils.convertDateTimeFromServer(data.assignedDateTime);
data.startDateTime = DateUtils.convertDateTimeFromServer(data.startDateTime);
data.endDateTime = DateUtils.convertDateTimeFromServer(data.endDateTime);
data.startDate = DateUtils.convertLocalDateFromServer(data.startDate);
data.endDate = DateUtils.convertLocalDateFromServer(data.endDate);
}
return data;
}
}
I am not sure how to pass a parameter to this get method or even how to call this method in the controller. How does one do this?
In your service add params
return $resource(resourceUrl, {}, {
'getTasksWithXYZ': {
method: 'GET',
params:{id:'#id'},
transformResponse: function (data) {
if (data) {
data = angular.fromJson(data);
data.assignedDateTime = DateUtils.convertDateTimeFromServer(data.assignedDateTime);
data.startDateTime = DateUtils.convertDateTimeFromServer(data.startDateTime);
data.endDateTime = DateUtils.convertDateTimeFromServer(data.endDateTime);
data.startDate = DateUtils.convertLocalDateFromServer(data.startDate);
data.endDate = DateUtils.convertLocalDateFromServer(data.endDate);
}
return data;
}
}
})
In your controller Task.getTasksWithXYZ(id)

angular then catch success error from services

I'm afraid I may have gone down the rabbit hole of recursive promises.
I have a service that handles my api. (It's got an extra layer of promise so that I could switch back to a local json if the api went offline. (Not sure how necessary it is anymore) - mayte I should eliminate it for simplicity).
Then I've got the promised async call in my controller.
This all works great as long as I get the data I expect, but it doesn't handle errors very well. When I get 400's and 500's, it doesn't send the error message to the user via toastr.
Sadly, this is not a fully-compliant RESTful api. The 400 error I get back is simply
{"Message":"No packages found"}
I don't really get how to get this to behave as it should, and replace success/error with then/catch (as per Angular best practice).
Here is a typical service call:
var _getPackagesPage = function (options) {
var pageSize = options.data.pageSize;
var page = options.data.page -1;
return $q (function(resolve, reject) {
switch (dataSource) {
case 'api'://staging - live api data
return $http({
method: 'get',
url: serviceBase + 'api/Packages?pageSize=' + pageSize + '&page=' + page
}).then(function(results) {
resolve(results);
});
break;
default: // dev - local json
$.getJSON('Content/data/Packages.json', function (json) {
var pageSize = options.data.pageSize;
var page = options.data.page;
var newjson = json.splice(page*pageSize,pageSize);
resolve(newjson);
});
}
});
};
and a typical call in a controller:
(options is the data object handed back to my data grid (Kendo))
vm.getPackages = function(options) {
return packagesService.getPackagesPage (options)
.then(function(results) {
options.success(results.data.Items);
})
.catch(function(error) {
options.error(error);
toastr.error(error.Message);
});
};
How can I clean this up?
[ UPDATE ] Attempted fix per Answer 1, below
Service:
var _getOrdersPage = function (options) {
var deff = $q.defer();
var pageSize = options.data.pageSize;
var page = options.data.page -1;
return $http({
method: 'get',
url: serviceBase + 'api/Packages?pageSize=' + pageSize + '&page=' + page
})
.then(
function(results) {
deff.resolve(results);
},
function(ex){
deff.reject(ex);
});
return deff.promise;
};
Controller:
vm.getOrders = function (options) {
return ordersService.getOrdersPage (options)
.then(function(results) {
console.log("results!");
console.log(results);
})
.catch(function(error) {
console.log("error!");
console.log(error);
});
};
results in:
GET http://< myURL >/api/Packages?pageSize=20&page=0 400 (Bad Request)
results!
undefined
I'm removing the switch case for brevity.
var _getPackagesPage = function (options) {
var pageSize = options.data.pageSize;
var page = options.data.page -1;
var deff = $q.defer();
$http({
method: 'get',
url: serviceBase + 'api/Packages?pageSize=' + pageSize + '&page=' + page
}).then(
function(results) {
deff.resolve(results);
},
function(ex){
deff.reject(ex);
});
return deff.promise;
};
Controller
vm.getOrders = function (options) {
return ordersService.getOrdersPage (options)
.then(
function(results) {
console.log("results!");
console.log(results);
},
function(error) {
console.log("error!");
console.log(error);
});
};
If you dont have any logic inside your service, then you could return the $http itself as $http inturn is a promise:
var _getPackagesPage = function (options) {
var pageSize = options.data.pageSize;
var page = options.data.page -1;
return $http({
method: 'get',
url: serviceBase + 'api/Packages?pageSize=' + pageSize + '&page=' + page
});
};
You have too many returns in your service. The second one is not called.
You don't need to create a promise manually since $http returns apromise.
You're not returning data from your service.
var _getOrdersPage = function(options) {
var pageSize = options.data.pageSize;
var page = options.data.page -1;
return $http({
method: 'get',
url: serviceBase + 'api/Packages?pageSize=' + pageSize + '&page=' + page
})
.then(
function(results) {
return results;
},
function(ex){
return ex;
});
}
Your controller is fine, you can use catch() or pass an error callback.
Example:
function myService($http) {
this.getData = function(url) {
return $http.get(url).
then(function(response) {
return response.data;
}, function(error) {
return error;
});
}
};
function MyController(myService) {
var vm = this;
vm.result = [];
vm.apiUrl = "https://randomuser.me/api/";
myService.getData(vm.apiUrl).then(function (data) {
vm.result = data;
},
function(error) {
console.log(error);
});
};
angular.module('myApp', []);
angular
.module('myApp')
.service('myService', myService)
.controller('MyController', MyController);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="MyController as ctrl">
{{ ctrl.result }}
</div>
</div>

GET call to REST API returns null

I am trying to make a GET call to test a REST API but it keeps returning null, is there anything I am doing wrong:
Making the call in controller.js
function ConsumerSearchCtrl($scope, BusinessCategoryService) {
console.log(BusinessCategoryService);
}
127.0.0.1:8000/api/category/ works perfectly fine
Code in services.js for API
/**
*
*/
function BusinessCategoryService(WenzeyAPI, $q) {
var scope = this;
scope.categories = categories;
function categories() {
var q = $q.defer();
WenzeyAPI.get('http://127.0.0.1:8000/api/category/').then(function success (res) {
q.resolve(res.data);
}, function failure (err) {
q.reject(err);
})
return q.promise;
}
}
/**
*
*/
function WenzeyAPI() {
var scope = this,
ip = "http://127.0.0.1:8000";
scope.get = get;
scope.post = post;
function get(url, data) {
data = data || {};
var req = {
method: 'GET',
url: url,
data: data
}
var q = $q.defer();
$http(req).then(function success(response) {
q.resolve(response);
}, function failure(err) {
q.reject(err);
});
return q.promise;
}
function post(url, data) {
data = data || {};
var req = {
method: 'POST',
url: url,
data: data
}
var q = $q.defer();
$http(req).then(function success(response) {
q.resolve(response);
}, function failure(err) {
q.reject(err);
});
return q.promise;
}
}
Removing WenzeyAPI and using $http resolved it.
function BusinessCategoryService($http) {
this.getAllData = function () {
return $http({
method: 'GET',
url: 'http://127.0.0.1:8000/api/category/',
});
}
}

How to do unit testing using jasmine on that factory?

I try to make a unit test on that code that consists of factory that take behavior Name and contracts an http request in a closure ?
var app = angular.module("behaviour",[]);
var behaviour = app.factory('Behaviours',['http',function(http){
var BehavioursJson = $http.get('data.json');
return {
getBehaviour : function(behaviourName) {
if (BehavioursJson[behaviourName]) {
var behaviour = BehavioursJson[behaviourName];
return function (behaviourData, callback) {
var keys = Object.allKeys(behaviourData);
var headers = {};
var data = {};
var url = behaviour.path;
// some process to fill headers and data objects
$http({
method: behaviour.method,
url: url,
data: data,
headers: headers
}).then(function successCallback(response) {
callback(response,null);
},function errorCallback(error) {
callback(null,error);
});
}
};
return null;
}
}
}]);
Note: using jasmine

Resources