I try to add 2 Services to my AngularJS Module. One should access my Employees and one my Products, but I get an Unknown provider: EmployeeServiceProvider <- EmployeeService <- BookingController.
All Javascript-Files are added to the html.
App/Module
var coffeewatchApp = angular.module('coffeewatchApp', [
'ngRoute',
'coffeewatchControllers',
'coffeewatchServices'
]);
//Routing
var coffeewatchControllers = angular.module('coffeewatchControllers', []);
var coffeewatchServices = angular.module('coffeewatchServices', []);
EmployeeService.js
var coffeewatchServices = angular.module('coffeewatchServices', ['ngResource']);
var employeeServiceUrlPart = "EmployeeService/";
coffeewatchServices.factory('EmployeeService', ['$resource',
function($resource){
return $resource('all/', {}, {
all: {method:'GET',url:REST_BASEURL+employeeServiceUrlPart+"all", params:{}, isArray:true}
});
}]);
ProductController.js is exactly the same but with Product
var coffeewatchServices = angular.module('coffeewatchServices', ['ngResource']);
var productServiceUrlPart = "ProductService/";
coffeewatchServices.factory('ProductService', ['$resource',
function($resource){
return $resource('all/', {}, {
all: {method:'GET',url:REST_BASEURL+productServiceUrlPart+"all", params:{}, isArray:true}
});
}]);
Controller accessing the two Services
coffeewatchControllers.controller('BookingController', ['$scope', 'EmployeeService', 'ProductService',
function ($scope, EmployeeService, ProductService) {
$scope.employees = EmployeeService.all();
$scope.products = ProductService.all();
}]);
Any help is appreciated; Thanks in advance.
EDIT:
I implemented the EmployeeService first and everything was working great.
So I don't really understand why adding the ProductService kills my EmployeeService. The only thing I can think of is that the ProductService somehow "overwrites" my EmployeeService because it gets injected second.
All added JS-Files in index.html
<script src="js/config/app-config.js"></script>
<script src="js/app.js"></script>
<script src="js/controllers/DashboardController.js"></script>
<script src="js/controllers/StatisticController.js"></script>
<script src="js/controllers/BookingController.js"></script>
<script src="js/services/EmployeeService.js"></script>
<script src="js/services/ProductService.js"></script>
EDITEDIT
After looking at this answer I am even more confused why my code is not working, but maybe the other code will help somone spotting the difference.
In both of your controller files, retrieve the module like this (remove dependency list) -
var coffeewatchServices = angular.module('coffeewatchServices');
Add the dependency to ngResource here instead, while declaring in App/Module -
var coffeewatchServices = angular.module('coffeewatchServices', ['ngResource']);
Your module is getting re-created on the second call in ProductController, so overriding previous module and service definitions.
Related
I have an angularJS app with three modules: myApp(parent/core module), services(contains all the factories and services), and controllers(contains all the controllers).
This is my app.js file
angular.module('services', []);
angular.module('controllers', []);
var app = angular.module('myApp', ['services', 'controllers']);
I read here that setting up my modules and defining dependencies in this way will allow each of my modules to access the other without having to inject the dependencies.
Here's my index.html file
<script src="/js/app.js"></script>
<script src="/js/services/testFactory.js"></script>
<script src="/js/controllers/testCtrl.js"></script>
testFactory.js file
angular.module('services').factory('testFactory', ['$rootScope', 'apiCall', function($rootScope, apiCall){
let testFactory = {};
testFactory.testFunc = function(){
console.log('testFactory.testFunc called');
}
return testFactory;
}])
testCtrl.js file
angular.module('controllers').controller('testCtrl', ['$scope', 'testFactory', function($scope, testFactory){
console.log("inside testCtrl");
$scope.testing = function(){
console.log("testing function called");
testFactory.testFunc();
}
}])
When I call the testFactory.testFunc inside the myApp module, it functions correctly. But, when I try calling it in the controller module, I'm getting the following error
TypeError: Cannot read property 'testFunc' of undefined
I even tried injecting the service module inside the controller module as a dependency, but I still got the same error.
How do I get the service module to work inside the controller module?
I have a factories called ReportService and IndexService. I want to use IndexService inside of ReportService.
But in ReportService, it says that the IndexService is undefined. I'm not quite sure why.
Here's my code so far:
indexService.js
angular.module('IndexService', []).factory('IndexService', ['$http', function ($http) {
return {
// Sending npm config from server (node) to front-end as JSON so we can use it in front-end.
// See localhost.json.
getConfig: function() {
return $http.get("/api/get-config");
}
}
}]);
reportService.js
angular.module('ReportService', []).factory('ReportService', ['$http', 'IndexService', function ($scope, $http, IndexService) {
// Sending npm config from server (node) to front-end as JSON so we can use it in front-end.
// See localhost.json.
IndexService.getConfig()
.then(function(response) {
var configs = response.data
});
return {
generateExcelReport: function(searchCriteriaList) {
var requestConfig = {
responseType: "arraybuffer",
headers: { "Content-Disposition": "attachment" }
};
// I want to call IndexService.getConfig()
// so I can change my base URL and port based on environment. My configs are in node.js back-end
var url = configs.url;
var port = configs.port;
return $http.post(url + ":" port + "/my-api-link", searchCriteriaList, requestConfig);
},
}
}]);
app.js
angular.module('myApp', ['ngStorage', 'ngRoute', 'appRoutes', 'IndexController', 'IndexService', 'ReportController', 'ReportService', 'PackageController', 'PackageService', 'FarmService', 'DesignService', 'UserService', 'oitozero.ngSweetAlert', 'ui.select', 'ui.materialize', 'ngSanitize', 'ngFileSaver'])
my index.html script imports
<!-- Our Angular Controllers and Services JS -->
<script src="./js/controllers/indexController.js"></script>
<script src="./js/controllers/reportController.js"></script>
<script src="./js/controllers/nerdController.js"></script>
<script src="./js/controllers/packageController.js"></script>
<script src="./js/services/indexService.js"></script>
<script src="./js/services/reportService.js"></script>
<script src="./js/services/farmService.js"></script>
<script src="./js/services/packageService.js"></script>
<script src="./js/services/designService.js"></script>
<script src="./js/services/userService.js"></script>
<script src="./js/appRoutes.js"></script>
<script src="./js/app.js"></script>
Kindly help. I've been over 2 hours on this and I can't still find the problem.. Thanks in advance :)
You need to inject it first, like:
angular
.module('ReportService')
.factory('ReportService', ReportService);
ReportService.$inject = ['IndexService'];
function ReportService(IndexService) {
// You code blah blah here
}
At least this is a way, how i am doing.
I have two controllers and one service in my angular app splitted in 3 different files as follows:
Main controller
var app = angular.module("app",[]);
app.controller("mainController", function(){
console.log("Hi main controller");
})
Second controller
var app = angular.module("app");
app.controller("secondController", ['myCoolService', function($rootScope, myCoolService){
console.log("Hi second controller")
}]);
Service
var app = angular.module("app");
app.service('myCoolService', function() {
});
I've made sure I was importing it correctly:
<script type="text/javascript" src="js/controllers/mainController.js"></script>
<script type="text/javascript" src="js/services/myCoolService.js"></script>
<script type="text/javascript" src="js/controllers/secondController.js"></script>
However I'm getting an unknown service exception:
Unknown provider: $resourceProvider <- $resource <- myCoolService
Can someone help me?
Should be:
var app = angular.module("app");
app.controller("secondController", ['$rootScope', 'myCoolService',
function($rootScope, myCoolService){
console.log("Hi second controller")
}
]);
See, AngularJS injector either gets names of specific dependencies from an array - or uses factory function arguments for them. The first way is actually recommended, as it withstands minification and lets Angular skip parsing the function's argument list.
The point is, AngularJS won't mix those approaches: if list of deps is specified, it IS used, and any hints given by arguments are just ignored. That's why your original code actually puts myCoolService into $rootScope variable (the first dependency is assigned to the first argument), but just doesn't know where to find the second one.
In your second controller you are missing dependency.
var app = angular.module("app");
app.controller("secondController", ['$rootScope', 'myCoolService', function($rootScope, myCoolService){
console.log("Hi second controller")
}]);
Whenever I do this:
app.controller('hangmanController', ['$scope', 'wordnickAPIService', function ($scope, wordnickAPIService) {
I get this:
[$injector:unpr] Unknown provider: wordnickAPIServiceProvider <- wordnickAPIService
I read through This discussion on the topic, but didn't see an answer that applied. I am sure it is something simple or trivial that I am missing, but, jeez, if Angular isn't giving me fits trying to piece it all together.
Relevant HTML:
<body ng-app="angularHangmanApp" ng-controller="hangmanController">
My controller:
'use strict';
var app = angular.module('angularHangmanApp', []);
app.controller('hangmanController', ['$scope', 'wordnickAPIService', function ($scope, wordnickAPIService) {
[...]variable declarations[...]
var wordListURL = 'http://long_url_that_returns_some_json';
$scope.wordList = wordnickAPIService.get(wordListURL);
}]);
My factory:
'use strict';
var app = angular.module('angularHangmanApp', []);
app.factory('wordnickAPIService', ['$http', function($http) {
return {
get: function(url) {
return $http.get(url);
},
post: function(url) {
return $http.post(url);
},
};
}]);
The problem is that you are creating multiple modules with the same name.
To create a module in angular you use:
var app = angular.module('angularHangmanApp', []);
Then to get That module somewhere else you just type:
var app = angular.module('angularHangmanApp');
No extra []...
Also make sure you declare the service before trying to call it.
In your factory and your controller, you are actually redefining the app module.
Instead of saying
var app = angular.module('angularHangmanApp', []);
say
var app = angular.module('angularHangmanApp');
Use the first style of invocation only once in your application (maybe just app.js). All other references should use the second style invocation, otherwise, you're constantly redefining the angular app and losing all of the controllers, factories, directives declared previously.
I'm using meteor + angular. My intention is to add more dependencies after the app bootstrap (This is because the package is the one handling the bootstrapping at the start and I don't have much control of it). Now while doing that, I would also want to enforce a basic code structure wherein for example, I would compile all controllers in one module.
Here's the basic idea:
'use strict';
angular.module('app.controllers', [])
.controller('MainCtrl', function() {
// ...
})
.controller('SubCtrl', function() {
// ...
})
.controller('AnotherCtrl', function() {
// ...
});
Then include that to the main module as dependency:
angular.module('app', [
'app.filters',
'app.services',
'app.directives',
'app.controllers' // Here
]);
After some research, I've discovered that what I'm trying to do (Adding dependencies after bootstrap) is actually a part of a feature request to the angular team. So my option is using, for example, $controllerProvider and register() function:
Meteor.config(function($controllerProvider) {
$controllerProvider.register('MainCtrl', function($scope) {
// ...
});
});
Meteor.config(function($controllerProvider) {
$controllerProvider.register('SubCtrl', function($scope) {
// ...
});
});
Meteor.config(function($controllerProvider) {
$controllerProvider.register('AnotherCtrl', function($scope) {
// ...
});
});
It's works though not that elegant. The questions are:
What's a more elegant way of doing the config and register part?
Is there a way to register a module instead?
Create your module:
angular.module('app.controllers', []);
Add it as a dependency:
angular.module('app').requires.push('app.controllers');
according to this presentation (slide 12) you can assign controllerProvider to app.
Example of replacing module's controller method: http://jsfiddle.net/arzo/HB7LU/6659/
var myApp = angular.module('myApp', []);
//note overriding controller method might be a little controversial :D
myApp.config(function allowRegisteringControllersInRuntime($controllerProvider) {
var backup = myApp.controller;
myApp.controller = $controllerProvider.register;
myApp.controller.legacy = backup;
})
myApp.run(function ($rootScope, $compile) {
myApp.controller('MyCtrl', function($scope) {
$scope.name = 'Superhero';
})
var elem;
var scope=$rootScope;
elem = $compile('<p ng-controller="MyCtrl">{{name}}</br><input ng-model="name" /></p>')($rootScope, function (clonedElement, scope) {
console.log('newly created element', clonedElement[0])
document.body.appendChild(clonedElement[0]);
});
console.log('You can access original register via', myApp.controller.legacy);
})
The only method that I've seen that works is replacing the angular.module function with your own function returning the module you used to bootstrap your app.
var myApp = angular.module('myApp', []);
angular.module = function() {
return myApp;
}
So that all modules that are registered afterwards are actually being registered in your myApp module.
This method combined with the one you describe in the question (using providers like $controllerProvider) will allow you to add "modules" after angular.bootstrap.
Demo
See this jsfiddle for a demo: https://jsfiddle.net/josketres/aw3L38r4/
Drawbacks
The config blocks of the modules that are added after angular.bootstrap will not be called. Maybe there's a way to fix this, but I haven't found it.
Overriding angular.module feels like a "dirty hack".