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;
I am writing a factory that returns a list of dog breeds from a php file but I can't return the response data to my controller. I have this as a factory
angular.module('myApp')
.factory('DataService, function($http) {
return {
get_breeds: function() {
method: 'GET',
url: 'http://localhost:8080/php/api/getbreeds.php'
}).then(function onSuccess(response) {
console.log(response); // responds with 200
return response.data;
}).catch(function onError(err) {
console.log(err);
})
}
}
});
and this is part of my component
angular.module('myApp')
.component('homeComponent', {
templateUrl: 'home.component.html,
controller: function (DataService) {
DataService.get_breeds()
.then(function(response) {
var dog_breeds = response;
console.log(dog_breeds)
});
...
But I'm not getting anything returned and an error message. Can someone guide me in the right direction?
I figured it out not long after I posted the question!
In the end I made a factory that just returned the data from the URL:
angular.module('myApp')
.factory('DataService', function($http) {
return {
get_dog_breeds: function(urlString) {
return $http.get(urlString)
}
}
})
And then called it in my component's controller like so:
DataService.get_dog_breeds('http://localhost:8080/php/api/getbreeds.php')
.then(function (response) {
console.log(response.data);
$scope.dog_breeds = response.data;
return $scope.dog_breeds;
}).catch(function (error) {
console.log('Error returned: ' + error
+ ' Please make sure the service you\'re trying to use exists');
return false;
});
And it just worked!
Loving AngularJS so far btw guys :)
Just return the http request from the service
angular.module('myApp')
.factory('DataService, function($http) {
var service = this;
service.get_breeds = function() {
return $http.get('http://localhost:8080/php/api/getbreeds.php')
}
}
});
Try doing this it should work
Use this in your factory
angular.module('myApp')
.factory('DataService', function($http) {
return {
get_breeds: function() {
var request = $http({
method: 'GET',
url: 'http://localhost:8080/php/api/getbreeds.php'
});
return request;
}
}
});
and use this in controller to retrieve the data
DataService.get_breeds()
.then(function(response){
console.log(response.data);
});
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 new on angular JS. I am tried to implement $http in the response of $http.
My issue is that when i call $http in response of anoter $http. It doesn't show the data on view. The view is rendered before the second $http call. I have used promises but no luck. Here is the code from other answer which i used by changing a little.
angular.module('App', [])
.controller('Ctrl', function($scope, resultsFactory) {
resultsFactory.all().then(
function(res){
$scope.results = res;
},
function(err){
console.error(err);
}
);
})
.factory('resultsFactory', function($http, $timeout, $q) {
var results = {};
function _all(){
var d = $q.defer();
$http({
url: url,
method: 'POST'
}).then(function (response) {
var f = {};
f.id = response.data.id;
f.name = response.data.name;
$http({
url: url,
data: "id="+response.data.parent_id,
method: 'POST'
}).then(function (response1) {
f.parentname = response1.name;
d.resolve(f);
});
});
return d.promise;
}
results.all = _all;
return results;
});
The id and name is shown properly on view but it is showing nothing for parent name. I have debug it. It is undefined when rendering view. After rendering it is setting their value to parentname. Can any one help me to resolve this issue?
You shouldn't need a deferred for this: just chain the promises:
return $http({
url: url,
method: 'POST'
}).then(function (response) {
var data = {};
data.id = response.data.id;
data.name = response.data.name;
return $http({
url: url,
data: "id="+response.data.parent_id,
method: 'POST'
}).then(function (response1) {
data.parentname = response1.name;
return data;
});
});
You overwrote your d variable...
.factory('resultsFactory', function ($http, $timeout, $q) {
var results = {};
function _all() {
var d = $q.defer();
$http({
url : url,
method : 'POST'
}).then(function (response) {
var secondD = {};
secondD.id = response.data.id;
secondD.name = response.data.name;
$http({
url : url,
data : "id=" + response.data.parent_id,
method : 'POST'
}).then(function (response1) {
secondD.parentname = response1.name;
secondD.resolve(d);
});
});
return d.promise;
}
results.all = _all;
return results;
});
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: ");
}
}