I am trying to wire up a simple data service to retrieve data from the server for http calls. I am using TypeScript to write the code. For some reason I can't get the service to see its dependencies.
Here is the service the way it is generated by Typescript
var app = angular.module('app',[]);
app.constant('baseUrl', 'http://localhost:63342');
//This follows the pattern created by Typescript
var myService = function(){
function myService($http, baseUrl){
this.$http = $http;
this.baseUrl = baseUrl;
this.http = typeof this.$http;
this.url = typeof this.baseUrl;
}
myService.$inject = ['$http', 'baseUrl'];
return myService
}
app.factory('myService', [
'$http', 'baseUrl',
myService
]);
app.controller('myCtrl',
['$scope', 'myService',
function($scope, myService){
$scope.httpType = myService.http;
$scope.urlType = myService.url}]
);
When I run the code locally the p tags get the ng-bind attributes set on them. But, of course, they have nothing in them. When I break on the $scope assignments, myService is available and it has the $inject variable, but none of the other 4 variables. The available examples for Typescript and angular are pretty thin. There must be something really basic I am doing wrong.
Here is a fiddle with the code. I don't know why the fiddle doesn't transclude the scope variables.
The issue is in :
var myService = function(){
function myService($http, baseUrl){
this.$http = $http;
this.baseUrl = baseUrl;
this.http = typeof this.$http;
this.url = typeof this.baseUrl;
}
myService.$inject = ['$http', 'baseUrl'];
return myService
}
app.factory('myService', [
'$http', 'baseUrl',
myService
]);
Angular will call myService with arguments $http,baseUrl which myService does not accept. So you need to do :
var myService = function($http, baseUrl){
this.$http = $http;
this.baseUrl = baseUrl;
this.http = typeof this.$http;
this.url = typeof this.baseUrl;
}
myService.$inject = ['$http', 'baseUrl'];
Alternatively if you want to use TypeScript classes use the same pattern I recommend for Controllers : http://www.youtube.com/watch?v=WdtVn_8K17E&hd=1 and use service instead of factory
I was able to get it to work following a module pattern to expose your service's properties, as well as using the inline notation to declare the service. Check out the plunker here: http://plnkr.co/edit/tVajIshcCegIwywGWL9Y?p=preview. Code pasted below for the script:
var app = angular.module('app',[]);
app.constant('baseUrl', 'http://developer.echonest.com/api/v4/artist/news?api_key=FILDTEOIK2HBORODV&id=7digital-US:artist:304&format=json');
app.factory('myService', ['$http', 'baseUrl', function($http,baseUrl){
var http = typeof $http;
var url = typeof baseUrl;
return {
http: http,
url : url
};
}]);
app.controller('myCtrl',
['$scope', 'myService',
function($scope, myService){
$scope.httpType = myService.http;
$scope.urlType = myService.url;
}]
);
Related
OK, I've built services before but obviously I don't actually know what makes them tick, since I can't seem to debug this ultra-simple service call:
app.js:
var gridApp = angular.module('gridApp', []);
gridApp.controller('mainController', ['$scope', '$http', 'dataService',
function($scope, dataService) {
$scope.message = 'I am Angular and I am working.';
var init = function(){
console.log(dataService.foo);
console.log(dataService.getData());
};
init();
}]);
dataService.js:
(function() {
'use strict';
angular
.module('gridApp')
.service('dataService', dataService)
dataService.$inject = [];
function dataService() {
console.log("I am the dataService and I am loaded");
var foo = 1;
function getData () {
return 2;
}
}
})();
I see this on-screen: I am Angular and I am working. so Angular is loading.
I see this in console: I am the dataService and I am loaded so the dataService is actually being loaded.
But then the console.log is:
undefined (line 8)
TypeError: dataService.getData is not a function (line 9)
What am I missing?
The previous answers are correct in that your $http injection was wrong, but you are also not attaching your service functions to the service:
function dataService() {
var dataService = this; //get a reference to the service
//attach your functions and variables to the service reference
dataService.foo = 1;
dataService.getData = function() {
return 2;
};
}
An Angular service is very simply an object class. It is also a singleton, meaning it's instantiated only once per run of your app. When the service is instantiated it is very much akin to calling the new operator on your dataService "class":
var $dataService = new dataService();
So, when you inject dataService into your controller, you are actually getting an instance, $dataService, of your dataService "class".
See this blog entry for further reading: https://tylermcginnis.com/angularjs-factory-vs-service-vs-provider-5f426cfe6b8c#.sneoo52nk
You are missing the 2nd parameter $http in the function. The named parameters and the actual parameters in function need to be the same, same order and same number. What happened before is that dataService was being assigned an $http instance and the actual dataService was not injected at all because there was no 3rd parameter to inject it into.
var gridApp = angular.module('gridApp', []);
gridApp.controller('mainController', ['$scope', '$http', 'dataService',
function($scope, $http, dataService) {
// ----was missing-----^
$scope.message = 'I am Angular and I am working.';
var init = function(){
console.log(dataService.foo);
console.log(dataService.getData());
};
init();
}]);
We have missed the second param '$http' in function. Just add the '$http' param, it should work fine
var gridApp = angular.module('gridApp', []);
gridApp.controller('mainController', ['$scope', '$http', 'dataService',
function($scope,$http, dataService) {
$scope.message = 'I am Angular and I am working.';
var init = function(){
console.log(dataService.foo);
console.log(dataService.getData());
};
init();
}]);
This is how I've been taught to set up services:
function dataService() {
var dataService = {};
var _foo = 1;
var _getData = function () { return 2; }
dataService.foo = _foo;
dataService.getData = _getData;
return dataService;
}
I believe this facilitates public/private methods/vars.
For reference, this is the full code accessing my service:
app.js:
var gridApp = angular.module('gridApp', []);
// create the controller and inject Angular's $scope
gridApp.controller('mainController', ['$scope', 'dataService', function($scope, dataService) {
// create a message to display in our view
$scope.message = 'Angular is working';
var init = function(){
getPackageData();
};
var getPackageData = function (){
return dataService.getData().then(
function successCallback(response) {
console.log(response);
},
function errorCallback(response) {
console.log(response);
}
);
};
init();
}]);
dataService.js:
(function() {
'use strict';
angular
.module('gridApp')
.service('dataService', dataService)
dataService.$inject = ['$http'];
function dataService($http) {
var dataService = {};
var _getData = function () {
return $http({
method: 'GET',
url: 'data/packages.json'
})
.then(function successCallback(response) {
return response;
},
function errorCallback(response) {
return response;
});
}
dataService.getData = _getData;
return dataService;
}
})();
I am trying to make an http call function in angular. The problem is that when I try running this on the Chrome console, it says "cannot read get of undefined." Obviously this is referring to the http get call, but it really looks to me like the http dependency was injected, so I am not sure what I am missing.
angular.module('app').controller("MainController", function($http, $scope ){
var vm = this;
vm.title = 'title';
vm.input = '';
$scope.submit = function (input, $scope, $http) {
$http.get("insert-url-here")
.success(console.log(input));
}
}
maybe you have some syntax error.
last time i worked with angular and the $http service i did something like this:
angular.module('app').controller('MainController', ['$scope', '$http', function($http, $scope ){
var vm = this;
vm.title = 'title';
vm.input = '';
$scope.submit = function (input) {
$http.get("insert-url-here")
.success(function(responseData) {
console.log(input));
});
}
//console.log(vm.input);
}]
You don't want to inject $scope and $http in your function. Injecting into you controller is sufficient. Should look like this:
$scope.submit = function (input) {
$http.get("insert-url-here")
.success(console.log(input));
//console.log(vm.input);
})]
If I need a to use a factory from another module do I need to add first the DI of the module to my current module and after that add the DI of the factory to the current factory? Or can I just add the factory itself (without its module)?
So if above its true the only use of Di in modules is for that use... or am i missing something else?
var myApp = angular.module('myApp', []);
myApp.service('myService', function() {
// do some stuff
});
myApp.controller('otherCtrl', function($scope, myService) {
// do some stuff
});
inject myApp module into otherApp module and use service myService:
var otherApp = angular.module('otherApp', ['myApp']);
otherApp.controller('myCtrl', function($scope, myService) {
$scope.myService = myService;
});
declare modules with dependecies.
var baseApp = angular.module("ERMSApp", ['ngSanitize', 'ngRoute', 'ngTable']);
var baseApp1 = angular.module("ERMSApp1", ['ERMSApp', 'ngSanitize', 'ngRoute', 'ngTable']);
declaring service.
baseApp.factory("getEmployeesService", function ($http) {
var promise;
var getEmployeesService = {
getEmployees: function () {
if (!promise) {
var promise = $http.get("/Timesheet/GetEmployees").then(function (result) {
return result;
});
}
return promise;
}
}
return getEmployeesService;
});
using service in another module
baseApp1.controller("leaveOnBehalfCtrl", function ($scope, $http, $filter, $sce, ngTableParams, $compile, getEmployeesService) {
getEmployeesService.getEmployees().then(function (data) {
$scope.employees = data.data;
})
});
I have about 10 controllers and 20 services.
Each controller uses at least 5 the same services and modules. For example:
app.controller('GroupsCtrl', function(
$rootScope,
$scope,
service1,
service2,
service3,
service4,
service5,
service6,
...
service20
)
{ /**/}
It seems pretty ugly and messy.
Is Angular provide any solution that will solve multi argument problem? For example new form:
app.controller('GroupsCtrl', function(
$rootScope,
$scope,
SomeObject, // goes here that contains other absent services
service6,
...
service20
)
{ /**/}
And SomeObject will install absent services:
SomeObject:[
service1,
service2,
service3,
service4,
service5,
]
So after that all my 10 controllers can inherit SomeObject instead to write full list each time.
Hope it was clear,
Thanks,
Yes you can. Create a factory which returns the services you want and use that factory in your controllers to access the services.
Ex.
var myapp = angular.module('myapp', []);
myapp.service('service1', function() {
this.test = function(){
console.log("Inside service1 -->test");
//alert("Inside service1 -->test")
}
});
myapp.service('service2', function() {
this.test = function(){
console.log("Inside service2 -->test");
//alert("Inside service2 -->test");
}
});
myapp.factory('servicesFactory', function(service1,service2) {
return {
service1 : service1,
service2 : service2
};
});
myapp.controller('Ctrl', function ($scope,servicesFactory) {
servicesFactory.service1.test();
servicesFactory.service2.test();
});
One simple solution can be using the $inject property annotation to inject the array of service names and referr the services using the arguments array as below.
//Common services array
var commonServices = ['$scope','$http'];
function initiateCtl(services){
this.scope = services[0]; this.http = services[1];
}
//Controller 1
var sampleCtrl = function(){
initiateCtl(arguments);
var $window = arguments[2];
console.log(scope);
};
sampleCtrl['$inject'] = commonServices.concat(['$window']);
app.controller('sampleCtrl', sampleCtrl);
//Controller 2
var sampleCtrl2 = function(){
initiateCtl(arguments);
var $location= arguments[2];
console.log(scope);
};
sampleCtrl2['$inject'] = commonServices.concat(['$location']);
app.controller('sampleCtrl2', sampleCtrl2 );
Trying to get ngResource to work, but getting the error:
Object # has no method 'query'
I've tried to keep it as simple as possible and according to the documentations/posts that I can find, this should work. But it doesn't.
Here's my service/factory:
var srcServices = angular.module('srcServices', ['ngResource']);
srcServices.factory('Rotation', ['$resource',
function ($resource) {
return $resource('/rotations/:id' );
}]);
And here's the controller code triggering the error:
var srcControllers = angular.module('srcControllers', ['ngResource']);
srcControllers.controller('RotationListCtrl', ['$scope', '$location', 'Rotation', function($scope, Rotation, $location) {
Rotation.query(function(data) {$scope.rotations = data;})
$scope.edit = function(a) {
var path = "/rotations/" + a._id.$oid;
$location.path(path);
};
}]);
Try this
var srcControllers = angular.module('srcControllers', ['ngResource', 'srcServices']);
You are creating the service as a new angular module. So in order to get access to the service you have to inject it to your controller.