I have a controller Device Controller. I am trying to access a function in service but I am getting an error -
TypeError: DeviceService1.addNewDevice is not a function
at ChildScope.$scope.submitDeviceDtls (CreateDeviceCtrl.js:175)
Here's my code
$scope.submitDeviceDtls = function () {
if ($scope.isNewDevice) {
DeviceService1.addNewDevice($scope.device).then(
function (res) {
console.log(JSON.stringify(res));
// logic
}
}
}
I have a service DeviceService1
function ($http, $q, ApiService, AuthService) {
return {
addNewDevice: function (deviceDtls) {
var deferred = $q.defer();
var payload = new FormData();
payload.append('deviceDtls', new Blob([JSON
.stringify(deviceDtls)], {
type: "application/json"
}));
// payload.append('profilePic', profile_pic);
payload.append('doctorId', AuthService.getDoctorId());
var req = {
method: 'POST',
headers: {
'Content-Type': undefined
},
transformRequest: angular.identity,
responseType: 'arraybuffer',
data: payload
}
ApiService.generic_post('/device/', req).then(
function (res) {
deferred.resolve(res);
}, function (error) {
deferred.reject(error);
}
);
return deferred.promise;
}
return DeviceService1;
Can someone help me? TIA
At your DeviceService1 you are returning firstly an object with the properties you need which includes the function (addnewDevice) you are trying to call but afterwards you return DeviceService1 (return DeviceService) which overrides the first return.
Just remove the following part:
return DeviceService1;
Related
I'm trying to pass data back to my controller from my service with no success. I am able to invoke my service from my controller, and I know the service itself works because I can console log the response from within the service (but not back in the controller).
This is my service:
(function () {
angular
.module('app')
.service('testService', testService);
testService.$inject = ['$http'];
function testService($http, url) {
var baseUrl = "http://getjsondata.com/" + url;
this.getData = function (url) {
$http({
method: 'GET',
url: baseUrl + url,
headers: {'Content-Type': 'application/json'}
})
.then(function (response) {
console.log(response); // THIS WORKS
return response;
})
.catch(function (error) {
return error;
});
};
}
}());
This is inside my controller:
vm.getTestData = function (url) {
vm.response = testService.getData(url);
console.log(vm.response);
};
I've tried passing the data back as a callback in testService.getData but with no success. I have also tried using a factory instead of a service but I'm not able to access the data back in my controller. I have also tried defining my function in the service differently (getData: function()...) and so on.
I'm guessing my return statement in the service is behaving differently than the way I am expecting. I would appreciate any help!
getData never returns. add return in front of $http and use .then in your controller.
this.getData = function (url) {
return $http({
method: 'GET',
url: baseUrl + url,
headers: {'Content-Type': 'application/json'}
})
};
In ctrl
vm.getTestData = function (url) {
testService.getData(url).then(function (response) {
vm.response = response;
return response;
})
.catch(function (error) {
return error;
});
};
I have some strange behaviour here....
I have a service I created to handle all API calls.
It looks like this:
angular.module('widget.data').service('apiHandler', apiHandler);
apiHandler.$inject = ['$http', 'SimpleCache', 'apiUrl', 'ngNotify'];
function apiHandler($http, simpleCache, apiUrl, ngNotify) {
return {
url: apiUrl,
get: get,
post: post,
put: put,
delete: requestDelete
};
//////////////////////////////////////////////////
// GET
function get(url, params) {
return buildRequest(url, 'GET', null, params);
};
// POST
function post(url, data) {
return buildRequest(url, 'POST', data);
};
// PUT
function put(url, data) {
return buildRequest(url, 'PUT', data);
};
// DELETE
function requestDelete(url, params) {
return buildRequest(url, 'DELETE', null, params);
};
// Private function to build our request
function buildRequest(url, method, data, params) {
//console.log(url);
// Create our apiPath
var apiPath = url.indexOf('http') > -1 ? url : apiUrl + url;
// Create the model
var model = {
method: method,
url: apiPath,
data: data,
params: params,
cache: simpleCache
};
// If we are performing an update/create or delete call
if (method !== 'GET') {
// Remove from our cache
simpleCache.remove(apiUrl + url);
}
// Build our request
return $http(model).then(function (response) {
// Return our response
return response.data;
// If we have an error
}, function (response) {
console.log(response.data.exceptionMessage);
// Display our error
ngNotify.set(response.data.exceptionMessage, { type: 'error' });
// Return our error
return response;
});
};
};
You can see in buildMessage it returns the call, response and error response. So I would expect that if there was an error, any service that has this injected into it would also fire the error callback.
But it doesn't.
I have this service:
angular.module('widget.directives').service('pkAuthenticateService', pkAuthenticateService);
pkAuthenticateService.$inject = ['apiHandler'];
function pkAuthenticateService(apiHandler) {
return {
register: register
};
//////////////////////////////////////////////////
function register(model) {
return apiHandler.post('users/create', model).then(function (response) {
console.log('success', response);
return response;
}, function (response) {
console.log('error', response);
return response;
});
};
};
But the message I get in the console is the success message and not the error.
Can someone explain to me why? Or help me get it working as I would expect (i.e. if it fails in the parent service, then it should fail all the way down).
It's one of the most interesting & confusing cases in JS promises - "swallowing" of errors. Consider following case:
var x = new Promise((result,reject)=>{
reject('something bad')
})
x.then(()=>{
console.log('wow')
return 'a';
},()=>{
console.log('ops')
return 'a';
}).then(()=>{
console.log('I\'m baaack')
return 'a';
},()=>{
console.log('still bad?')
return 'a';
})
It might be counterintuitive, but inside 2nd then() 'I\'m baaack' will be printed because you have already caught & handled error. So, if you're handling error, either with 2'nd parameter of then() or with some "catch", you need to throw an error or return something rejected to pass error further down.
In your case, it can be done without $q, just replace 1 line:
// If we have an error
}, function (response) {
console.log(response.data.exceptionMessage);
// Display our error
ngNotify.set(response.data.exceptionMessage, { type: 'error' });
// Return our error
throw response;
});
The catch function returns a resolved promise not a rejected promise:
The Promise returned by catch() is rejected if onRejected throws an error or
returns a Promise which is itself rejected; otherwise, it is resolved.
In order for the rejected promise to percolate through to the outer function (or to "fail all the way down" as you say), you need to return it as a rejected promise:
return $http(model).then(function (response) {
...
}, function (response) {
...
// Return our error
return $q.reject(response);
});
Inject the $q service of angular for managing promises.
Then create a deferral from $q and perform your request. Inside the result of your request, resolve or reject the promise providing the data. Then return the deferred object.
So changing your service in this way should work:
angular.module('widget.data').service('apiHandler', apiHandler);
apiHandler.$inject = ['$http', 'SimpleCache', 'apiUrl', 'ngNotify', '$q'];
function apiHandler($http, simpleCache, apiUrl, ngNotify, $q) {
return {
url: apiUrl,
get: get,
post: post,
put: put,
delete: requestDelete
};
//////////////////////////////////////////////////
// GET
function get(url, params) {
return buildRequest(url, 'GET', null, params);
};
// POST
function post(url, data) {
return buildRequest(url, 'POST', data);
};
// PUT
function put(url, data) {
return buildRequest(url, 'PUT', data);
};
// DELETE
function requestDelete(url, params) {
return buildRequest(url, 'DELETE', null, params);
};
// Private function to build our request
function buildRequest(url, method, data, params) {
//console.log(url);
// Create our apiPath
var apiPath = url.indexOf('http') > -1 ? url : apiUrl + url;
// Create the model
var model = {
method: method,
url: apiPath,
data: data,
params: params,
cache: simpleCache
};
// If we are performing an update/create or delete call
if (method !== 'GET') {
// Remove from our cache
simpleCache.remove(apiUrl + url);
}
var deferred = $q.defer();
$http(model).then(function (response) {
// Return our response
$q.resolve(response.data);
// If we have an error
}, function (response) {
console.log(response.data.exceptionMessage);
// Display our error
ngNotify.set(response.data.exceptionMessage, { type: 'error' });
// Return our error
$q.reject(response);
});
return deferred;
};
};
I am trying to send the http response as a JSON body to an error handler if an error occurs. I am not really sure how to do this as I am a little inexperienced in this area. Here is the relevant code that I have currently:
Controller:
for (var prop in $scope.applicants) {
var applicant = $scope.applicants[prop];
$scope.sendApplicantsToSR(applicant).then(null, $scope.sendATSError.bind(null, applicant));
}
$scope.sendATSError = function (applicant, error) {
return AtsintegrationsService.applicantErrorHandling(applicant.dataset.atsApplicantID);
};
$scope.sendApplicantsToSR = function(applicant) {
return AtsintegrationsService.sendApplicantsToSR(applicant);
};
Service:
srvc.sendApplicantsToSR = function (applicant) {
var applicantURL = {snip};
return $http({
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
method: 'POST',
url: applicantURL,
data: applicant
});
};
srvc.applicantErrorHandling = function (applicantID, error) {
var url = srvc.url + {snip};
return $http({
method: 'POST',
url: url,
data: { "error_message": error }
});
};
So, ideally, I would like to pass the result of $scope.sendApplicantsToSR to $scope.sendATSError only when an error occurs.
Inside your controller
YourService.getdatafromservice().then(function(SDetails) {
//response from service
console.log(SDetails);
});
Inside your service
return {
getData: getData
};
function getData() {
var req = $http.post('get_school_data.php', {
id: 'id_value',
});
return req.then(handleSuccess, handleError);
function handleSuccess(response) {
response_data = response.data;
return response_data;
}
function handleError(response) {
console.log("Request Err: ");
}
}
I'm creating service layers to interact with Rest server, but I've got some problems with ngResource promises.
var grupogestion= angular.module('app.grupogestion.services', ['ngResource']);
grupogestion.factory('Grupogestion', ['$resource', function ($resource){
return $resource('api/grupogestiones/:action/:id.:format',
{
action: '#action', id:'#id', format:'json'
},
{
'get': {method:'GET'},
'post': {method:'POST',headers : {'Content-Type': 'application/x-www-form-urlencoded'}},
'save': {method: 'POST',headers : {'Content-Type': 'application/x-www-form-urlencoded'}}
}
);
}]);
grupogestion.service('GrupogestionService',['Grupogestion', function (Grupogestion){
this.findAll = function (){
Grupogestion.get({action: 'index'},function (data, status, headers, config){
return data;
});
}
this.save = function (grupogestion){
Grupogestion.save({'action':'add'},$.param(grupogestion)).$promise.then(
function(data){
alert('k');
return data;
},
function(error){
alert('j');
return error;
}
);
}
}]);
When I call var response = GrupogestionService.save(data) from angular controller, I don't get the data at the same time I call the function, so the question is: How can I modify GrupogestionService for returning data to the controller?
I've tried to return the promise but I couldn't do it. Thanks for helping.
// service code
grupogestion.service('GrupogestionService', ['Grupogestion', function (Grupogestion) {
this.findAll = function () {
Grupogestion.get({action: 'index'}, function (data, status, headers, config) {
return data;
});
};
this.save = function (grupogestion) {
return Grupogestion.save({'action': 'add'}, $.param(grupogestion));
}
}]);
//run in your controller
var response = GrupogestionService.save(data).$promise.then(
function (data) {
alert('k');
return data;
},
function (error) {
alert('j');
return error;
}
);
I have Employee controller which is having property Id, Name , Specification. I have made one Employee service which is having ajax call and get employee list. But every time getting '' in User.
When i debug the code i found that it call success first and then it goes for Ajax call.
When i do ajax call without service it works fine.
angular.module('EmployeeServiceModule', [])
.service('EmployeeSer', ['$http',function ($http) {
this.Users = '';
this.errors = '';
this.SearchEmployee = function () {
// Ajax call
$http({
method: 'GET',
url: '/Home/GetEmployeeList',
params: { filterData: 'Test' },
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
}).then(onSuccess, onError);
var onSuccess = function (response) {
this.userUsers = response.data;
this.errors = '';
};
var onError = function (reason) {
this.userUsers = reason;
this.errors = "Error in retrieving data.";
};
return this.Users;
}
}]);
angular.module('Employee', ['EmployeeServiceModule'])
.controller('EmployeeController', ['EmployeeSer', '$scope', '$http', function (EmployeeSer, $scope, $http) {
this.Id = '';
this.name = '';
this.expertise = '';
$scope.repoSortOrder = 'id';
$scope.filterField = '';
// Call to service
this.GetAllEmployee = function () {
// Initiates the AJAX call
$scope.User = EmployeeSer.SearchEmployee();
// Returns the promise - Contains result once request completes
return true;
};
this.AddEmployee = function () {
var empData = {
Id: $("#txtId").val(),
Name: $("#txtName").val(),
Expertise: $("#expertise").val()
};
$http({
method: 'POST',
url: '/Home/Create',
params: JSON.stringify(empData),
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
}).then(onSuccess, onError);
// Returns the promise - Contains result once request completes
return true;
};
var onSuccess = function (response) {
$scope.user = response.data;
$scope.error = '';
};
var onError = function (reason) {
$scope.error = "Error in retrieving data.";
};
}]);
It's because you are returning the users before the data is fetched from the server. Also it doesn't seem like you are assigning them correctly.
Here are two ways to solve the problem:
Firstly. You bind your controller user-data to the user-data in the service.
angular.module('EmployeeServiceModule', [])
.service('EmployeeSer', ['$http',function ($http) {
this.Users = '';
this.errors = '';
$http({
method: 'GET',
url: '/Home/GetEmployeeList',
params: { filterData: 'Test' },
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
}).then(onSuccess, onError);
var onSuccess = function (response) {
this.Users = response.data;
this.errors = '';
};
var onError = function (reason) {
this.users = null;
this.errors = "Error in retrieving data.";
};
}
}]);
angular.module('Employee', ['EmployeeServiceModule'])
.controller('EmployeeController', ['EmployeeSer', '$scope', '$http', function (EmployeeSer, $scope, $http) {
this.users = EmployeeSer.users;
EmployeeSer.SearchEmployee();
}]);
And the second way would be to return the promise in the service and unwrap it in the controller.
angular.module('EmployeeServiceModule', [])
.service('EmployeeSer', ['$http',function ($http) {
this.SearchEmployee = function () {
return $http({
method: 'GET',
url: '/Home/GetEmployeeList',
params: { filterData: 'Test' },
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
});
}
}]);
angular.module('Employee', ['EmployeeServiceModule'])
.controller('EmployeeController', ['EmployeeSer', '$scope', '$http', function (EmployeeSer, $scope, $http) {
this.GetAllEmployee = function () {
EmployeeSer.SearchEmployee()
.then(onSuccess, onError)
};
var onSuccess = function (response) {
$scope.user = response.data;
$scope.error = '';
};
var onError = function (reason) {
$scope.error = "Error in retrieving data.";
};
}]);
OFF TOPIC
You should probably consider using ngModel instead of jQuery to get you data to the controller.
Not like this:
var empData = {
Id: $("#txtId").val(),
Name: $("#txtName").val(),
Expertise: $("#expertise").val()
};
// Here serverRequest is my service to make requests to the server
serverRequest.postReq = function(url, data, sucessCallback, errorCallback){
$http({
method: 'POST',
url: urlToBeUsed,
data:data,
headers : {'Content-Type': 'application/x-www-form-urlencoded'}})
.success(function(data, status, headers, config) {
sucessCallback(data);
})
.error(function(data, status, headers, config){
errorCallback(data);
})
}
// In the controller
serverRequest.postReq('urlToBeCalled', dataToBeSent, scope.successCb, scope.errorCb);
scope.successCb = function(data){
// functionality to be done
}
scope.errorCb = function(data){
// functionality to be done
}
Try it this way your problem might be solved
Promise must be unwrapped in your controller if you want to use it