I'm trying to learn how to use Angular right, by having all my business logic in services.
When I do a post request in a service, I get the following error:
Cannot read property 'post' of undefined
Here is some code:
UrlApp.controller('UrlFormCtrl', UrlFormCtrl);
UrlApp.factory('addUrlService', addUrlService);
function UrlFormCtrl($scope, $http) {
console.log('Url Form Controller Initialized');
$scope.addUrl = addUrlService.bind(null, $http);
}
function addUrlService($scope, $http){
console.log('initializing addUrlService');
return $http.post('urls/create', {'test':'test'}).then(function(response){
return response.data;
});
}
I'm just getting the hang of Angular, so I'm not entirely sure what I'm doing wrong. See any problems?
Firstly, you don't need to inject $scope in your service.
Secondly, you don't need to inject $http service in your controller.
Thirdly, you need to inject the service in your controller.
Finally, addUrlService service is returning a promise meaning it will make a request when service is instantiated. You may want to return a function instead or an object containing several functions.
So I would change your code to:
UrlApp.controller('UrlFormCtrl', UrlFormCtrl);
UrlApp.factory('AddUrlService', AddUrlService);
function UrlFormCtrl($scope, AddUrlService) {
$scope.addUrl = AddUrlService.addUrl;
}
function AddUrlService($http) {
function addUrl() {
return $http.post('urls/create', {
'test': 'test'
}).then(function (response) {
return response.data;
});
}
return {
addUrl: addUrl
};
}
Can you try like this
UrlApp.controller('UrlFormCtrl', UrlFormCtrl);
UrlApp.factory('addUrlService', addUrlService);
function UrlFormCtrl($scope,addUrlService) {
console.log('Url Form Controller Initialized');
$scope.addUrl = addUrlService;
}
function addUrlService($http){
console.log('initializing addUrlService');
return $http.post('urls/create', {'test':'test'}).then(function(response){
return response.data;
});
}
Related
I need to pass a value from an input field on the view using a service. The service should call my WebAPI2 and then receives an valid JSON as a response.
However, I am either getting an promise object, which I cannot resolve (even with ".then()"), or if I'm using an factory it won't compile as it seems to not implement the $get method.
The JSON Object I'm returning is also valid.
View :
<div class="input" ng-controller="InputController as ctrl">
<input ng-model="inputdata" /> {{inputdata}}
<button ng-click="ctrl.gibDaten(inputdata)">Senden</button>
{{cooledaten}}
</div>
Controller :
module GoogleMapsApp {
myApp.myAppModule.controller("InputController",
["$scope", "mapsServiceCustom",
function ($scope, mapsServiceCustom) {
$scope.lEingabedaten = $scope.inputdata;
this.gibDaten = function () {
$scope.cooledaten = mapsServiceCustom.gibDaten().then();
console.log($scope.cooledaten);
}
}]);
}
Service:
module GoogleMapsApp {
myApp.myAppModule.service("mapsServiceCustom",
["$http",
function ($http) {
this.gibDaten = function (lEingabe) {
console.log(lEingabe);
console.log($http.get("api/getDistanceData/" + lEingabe + "/Cologne")
.then(function(data) {
return data;
Controller:}));
return $http.get("api/getDistanceData/" + lEingabe + "/Cologne")
.then(function (data) {
return data;
});
//return $http.get("api/getDistanceData/" + lEingabedaten1 + "/Cologne");
}
}
]);
}
Console log:
Object { $$state: Object }maps.serviceCustom.js:14:17
Object { $$state: Object }InputController.js:8:17
If I check the $$state:Object it contains exactly the desired data.
Using a factory leads me to the following error:
https://docs.angularjs.org/error/$injector/undef?p0=mapsServiceCustom
So what am I doing wrong? How would I implement my intend?
You need to pass a function to then part...
So just put then function in your controller and set returning response to your variable...
myApp.myAppModule.controller("InputController",
["$scope", "mapsServiceCustom",
function ($scope, mapsServiceCustom) {
$scope.lEingabedaten = $scope.inputdata;
this.gibDaten = function () {
mapsServiceCustom.gibDaten().then(function(response){
// set response to your variable
$scope.cooledaten = response;
});
}
}]);
You have not implemented the service properly. please go through the following link (Angularjs official documentation)
https://docs.angularjs.org/guide/services
You need to expose your API by returning it an js object.(Same thing is shown in your error link. please refer to that as well)
module GoogleMapsApp {
myApp.myAppModule.service("mapsServiceCustom",
["$http", function ($http) {
this.gibDaten = function (lEingabe) {
console.log(lEingabe);
console.log($http.get("api/getDistanceData/" + lEingabe + "/Cologne")
.then(function(data) {
return data;
}
}
return { gibDaten: this.gibDaten};
}]);
}
Here You can learn more on $get
method https://docs.angularjs.org/guide/providers
I'm fairly new to AngularJS and have just begun to grasp many of the concepts I especially like the MVC design pattern. But I am having a difficult time implementing the Service layer in my application.
What I am finding is that after my Controller calls a method within the service, it continues with code execution before the service returns the data; so that by the time the service does return the data, it isn't of any use to the controller.
To give a better example of what I'm saying, here is the code:
var InsightApp = angular.module('InsightApp', ['chart.js']);
// Module declaration with factory containing the service
InsightApp.factory("DataService", function ($http) {
return {
GetChartSelections: function () {
return $http.get('Home/GetSalesData')
.then(function (result) {
return result.data;
});
}
};
});
InsightApp.controller("ChartSelectionController", GetAvailableCharts);
// 2nd Controller calls the Service
InsightApp.controller("DataController", function($scope, $http, DataService){
var response = DataService.GetChartSelections();
// This method is executed before the service returns the data
function workWithData(response){
// Do Something with Data
}
}
All the examples I've found seem to be constructed as I have here or some slight variation; so I am not certain what I should be doing to ensure asynchronous execution.
In the Javascript world, I'd move the service to the inside of the Controller to make certain it executes async; but I don't how to make that happen in Angular. Also, it would be counter intuitive against the angular injection to do that anyway.
So what is the proper way to do this?
http return a promise not the data, so in your factory your returning the $http promise and can use it like a promise with then, catch, finally method.
see: http://blog.ninja-squad.com/2015/05/28/angularjs-promises/
InsightApp.controller("DataController", function($scope, $http, DataService){
var response = DataService.GetChartSelections()
.then(function(res) {
// execute when you have the data
})
.catch(function(err) {
// execute if you have an error in your http call
});
EDIT pass params to model service:
InsightApp.factory("DataService", function ($http) {
return {
GetChartSelections: function (yourParameter) {
console.log(yourParameter);
return $http.get('Home/GetSalesData')
.then(function (result) {
return result.data;
});
}
};
});
and then :
InsightApp.controller("DataController", function($scope, $http, DataService){
var response = DataService.GetChartSelections('only pie one')
.then(function(res) {
// execute when you have the data
})
.catch(function(err) {
// execute if you have an error in your http call
});
You should proceed like this :
DataService.GetChartSelections().then(function (data) {
workWithData(data);
}
Actually $http.get returns a Promise. You can call the method then to handle the success or failure of your Promise
Should it not be like this, when your $http returns a promise or you pass a callback.
With passing callback as a param.
InsightApp.factory("DataService", function ($http) {
return {
GetChartSelections: function (workWithData) {
return $http.get('Home/GetSalesData')
.then(function (result) {
workWithData(result.data);
});
}
};
});
Controller code:
InsightApp.controller("DataController", function($scope, $http, DataService){
var response = DataService.GetChartSelections(workWithData);
// This method is executed before the service returns the data
function workWithData(response){
// Do Something with Data
}
}
Or use then or success:
var response = DataService.GetChartSelections().then(function(res){
//you have your response here... which you can pass to workWithData
});
Return the promise to the controller, dont resolve it in the factory
var InsightApp = angular.module('InsightApp', ['chart.js']);
// Module declaration with factory containing the service
InsightApp.factory("DataService", function ($http) {
return {
GetChartSelections: function () {
return $http.get('Home/GetSalesData');
}
};
});
In the controller,
var successCallBk =function (response){
// Do Something with Data
};
var errorCallBK =function (response){
// Error Module
};
var response = DataService.GetChartSelections().then(successCallBk,errorCallBK);
Currently writing a prototype app in Ionic, pretty new to ionic and angular. I've written a small JSON API with about 25 objects in it, I've been able to display the list of them on a page we'll call "Library", I'm trying now to use those list items as links to an individual page for each item we will call a "Lesson". The variable $scope.lessonId is being set properly in the controller but being set as undefined in the service. Is it possible to achieve what I'm trying to, or am I just flat out doing this wrong?
.controller('LibraryLessonCtrl', function($scope, $stateParams, LessonService) {
$scope.lessonId = $stateParams.libraryId;
console.log($scope.lessonId);
LessonService.getLessonId()
.then(function(response){
$scope.lesson = response;
console.log($scope.lesson);
});
})
.service ('LessonService', function($http){
return { getLessonId: function() {
return $http.get('api/postsAPI.json')
.then(function (response, lessonId) {
console.log(lessonId);
for(i=0;i<response.data.length;i++){
if(response.data[i].post_id == lessonId){
return response.data[i];
}
}
});
}
};
})
You have to pass your $scope.lessonId variable to your service call if you like to use the value inside your service.
.controller('LibraryLessonCtrl', function($scope, $stateParams, LessonService) {
$scope.lessonId = $stateParams.libraryId;
console.log($scope.lessonId);
LessonService.getLessonId($scope.lessonId)
.then(function(response){
$scope.lesson = response;
console.log($scope.lesson);
});
}).service ('LessonService', function($http){
return { getLessonId: function(lessonId) {
return $http.get('api/postsAPI.json')
.then(function (response) {
console.log(lessonId);
for(i=0;i<response.data.length;i++){
if(response.data[i].post_id == lessonId){
return response.data[i];
}
}
});
}
};
})
You could do it by passing Id to service and storing it there. Please try not to pass $scope variable to service as it is not a good practice. You can do following:
.service ('LessonService', function($http){
var lessionId;
return {
/*other methods*/
setLessionId: function(id) {
lessionId = id;
},
getLessionId: function(){
return lessionId;
}
};
})
I have following controller code
module.registerController('DemoCtrl', function ($scope, myFactory) {
myFactory.get(function (data) {
console.log(data); /// data is always undefined
});
});
and following the factory which is calling restful webapi
module.registerFactory('myFactory', ['$http',
function ($http) {
function get(callback) {
$http.get('mywebapiurl')
.success(function (response) {
//debugger; data comes back from server
callback(response);
}).error(function (response, status, headers, config) {
callback(response);
});
}
return {
get: get
}
}]);
The factory is calling webapi service and does gets the data back. However in controller the data doesnt get returned.
Am I missing something obvious here? Also not sure if this is the best way to call webservice in angularjs in controller using factory. Any inputs are most welcome.
Thanks,
You want to return a promise instead of passing a callback. As $http.get already returns a promise, you can just return that, or a derived promise that returns the response data directly. By the way, your factory looks like it should be a service instead:
angular.moudule('yourApp')
.service('myService', ['$http', myService]);
function myService($http) {
this.get = function(url) {
return $http.get(url)
.then(function transformData(response){
return response.data;
}).catch(function onError(rejectionResponse){
//Whatever you want to do here
});
}
}
This way myService.get will return a promise you can .then(), .catch() and .finally() on what you want, staying in the frameworks coding style. For example:
var squirrels = [];
myService.get('http://squirrelshop.com/api/squirrels')
.then(function(squirrelsData){
console.log('Got the squirrels!');
squirrels = squirrelsData;
}).catch(function(rejection){
console.warn('Couldnt fetch squirrels. Reason: ' + rejection);
});
controller code
module.registerController('DemoCtrl', function ($scope, myFactory) {
myFactory.get("url").then(function(d) {
console.log(d.data);
}
});
});
factory which is calling restful webapi
module.registerFactory('myFactory', ['$http',
function ($http) {
var apiFactory = {
get:function(url){
return $http.get(url);
}
}
return apiFactory;
}]);
Success and failure in factory
module.registerFactory('myFactory', ['$http',
function ($http) {
var apiFactory = {
get:function(url){
return $http.get(url).then(function(response){
// success
return responce.data;
},function(error){
//failure
return error;
};
}
}
return apiFactory;
}]);
I am making a simple get request using $http .and it fails with 503-service unavailable error which is clearly shown in the network tab .But the rejection object in the responseError interceptor object shows status: 0.
Here is my Interceptor
angular.module("app", []).config(function($httpProvider){
$httpProvider.interceptors.push(function($q) {
return {
'responseError': function(rejection) {
console.log(rejection);
}
}
})
});
I am expecting status code 503 in the interceptor but i am getting 0.Please help me to understand and resolve the issue.
Here is a fiddle illustrating the issue.
The request is a cross domain request.
The service you are using does return any data. Angular $http expects some data to be returned, and in this case "GetStatusCode" just stops and does not return anything.
Also, fyi - your fiddle does not respect angular's method of binding to a controller, which expects a string for the controller name.
See http://plnkr.co/edit/x46D5FIsgaKsaSocYjpz?p=preview for proper markup.. where we name the controller as a string, for ex:
angular.module("plunker", [])
.config(function ($httpProvider) {
$httpProvider.interceptors.push(function () {
return {
'responseError': function (rejection) {
console.log('rejection = ', rejection);
},
'response': function (response) {
console.log('response = ', response);
}
}
})
})
.controller('Controller', function Controller($scope, $http) {
$scope.getCode = function () {
var req = 'http://www.reddit.com/r/catpictures.json?limit=50&jsonp=JSON_CALLBACK';
return $http.jsonp(req);
};
$scope.get = function () {
return $scope.getCode()
};
})
;