Separation of AngularJS controller files? - angularjs

I'm getting an error when running my app: Argument 'AppCtrl' is not a function, got undefined - I believe it has something to do with the separation of controller files?
Ok, so I have in my first file: app.js this:
angular.module('zerochili', [
'ionic',
'zerochili.controllers',
'zerochili.services',
'zerochili.directives'
])
Then I have some different controller files - Lets take the file there the AppCtrl is - This looks like the following:
angular.module('zerochili.controllers', [])
.controller('AppCtrl', ['$scope', '$ionicModal', '$timeout', function ($scope, $ionicModal, $timeout){
}])
And another file fx like so:
angular.module('zerochili.controllers', [])
.controller('LoginCtrl', ['$scope', '$state', '$ionicPopup', '$timeout', function($scope, $state, $ionicPopup, $timeout){
}]);
What am I doing wrong? Can't seem to quite figure it out?

You can think of your app.js as the part where you define the module. The controller files should be adding to the module (not have ", []" as this creates the module).
You should probably be doing this in your controllers
angular.module('zerochili')
.controller('AppCtrl', etc.
So, remove these: 'zerochili.controllers', 'zerochili.services', 'zerochili.directives' from the app.js and add your controllers,services and directives to the 'zerochili' module like above.
If you want to keep, for example, 'zerochili.controllers' make sure that you don't create this module twice, i.e. have angular.module('zerochili.controllers', []) twice.

It's only because you are creating a new modul with []
you can put at the end of your app.js
angular.module('zerochili.controllers', []);
angular.module('zerochili.directives', []);
angular.module('zerochili.services', []);
and then use it like this:
angular.module('zerochili.controllers')...

Related

Unknown provider error when injecting AngularJS factory into controller

I'm trying to inject my factory into my controller and I'm getting this error from AngularJS:
Error: $injector:unpr Unknown Provider
I have looked through almost all of the questions on here and still cannot find a solution to my problem. I believe my controller and factory and declared correctly and the injection is correct but it looks like this isn't the case.
My factory code is as follows:
var app = angular.module('test', []);
app.factory('processingFactory', function () {
var factory = {};
factory.newTest = function() {
console.log("TEST");
}
return factory;
});
This is then injected into the controller which looks like this:
angular.module("test", ["angularModalService", "anguFixedHeaderTable",
'angular-loading-bar', "ngResource", "agGrid",
'ui.tree']).controller("dashboardController", [
"$scope",
"$timeout",
"$http",
"$window",
"$interval",
"$resource",
"ModalService",
"$filter",
'$q',
'processingFactory',
function($scope, $timeout, $http, $window, $interval, $resource,
ModalService, $filter, $q, processingFactory) {
//other code removed
$scope.newWorkorder = processingFactory.newWorkorder;
}
]);
This function is called through a button click on the web page. All of the files needed are in script tags on this html page. I am fairly new to angular so this could be a simple error or something I am not aware of.
Calling angular.module with an array as the second argument declares a module, which can only happen for any given module name. You are declaring the module twice (once in your controller code, and again in your factory code).
Try changing the first part of your factory code to:
var app = angular.module('test');
If you are doing the same thing elsewhere in the app you will need to remove the second argument there too, so that there is only one module declaration in the whole app.
if there are any dependencies for your module "test" why do not you have them declared in the first line itself like:
var app = angular.module("test", ["angularModalService", "anguFixedHeaderTable",
'angular-loading-bar', "ngResource", "agGrid",
'ui.tree']);
Then declare your controller like::
app.controler(...)
Things should work fine.

$timeout is not a function error

Hey guys got a little problem that i cant seem to see the problem for. Im building an angular application and im getting the error stated in the question title. Ive injected the $timeout to the controller but im still getting an error with this bit of code can some one tell me where i may be going wrong?
cheers
(function() {
'use strict';
angular
.module('my.module')
.controller('NewSearchController', NewSearchController);
NewSearchController.$inject = ['$rootScope', '$scope', '$location','UserService',
'SearchService', '$window', '$controller', '$mdDialog', 'ModalService', '$routeParams', '$timeout'];
/**
* #namespace ContactController
*/
function NewSearchController($rootScope, $scope, $location, UserService, SearchService, $window, $controller, $mdDialog, $routeParams, $timeout)
Timeout code:
var timerMax = false;
$scope.$watch(NewSearchController.searchObject.maxDayRate, function(){
if(timerMax) {
$timeout.cancel(timerMax);
}
timerMax= $timeout(function() {
NewSearchController.updateSearchFilters();
}, 5000);
});
The problem is in your injection: 'ModalService' listed as injectable but not one of the parameters so angular will inject 'ModalService' and the values you get for parameters later in the list are all wrong.
If you use something like gulp to build your app then use gulp-ng-annotate to build the injection list automatically. That way it won't go wrong and you never have to worry about it.
'$mdDialog', 'ModalService', '$routeParams', '$timeout']
$mdDialog, $routeParams, $timeout
these two dnt match Change it to
$mdDialog,ModalService, $routeParams, $timeout
you have injected $timeout at position 11th position in controller but in function it is at 10th position as u have missed ModalService in function.So the error is just because of this . You need to inject and add the dependcies at same position otherwise it wont work.

`unknown provider` error if not using global app variable

I have three different application files (in addition to vendor files) for my angular app loaded in this order
app.js
store.js
controller.js
The code from the different files is only visible to the others if I'm using a global variable, however, I thought if I used modules by starting each file like this
angular.module('myApp',
then I could avoid a global and have code defined in each file available to the others.
Example
if I do it this way with the global variable myApp then the storage provider is available in the controller.
var myApp = angular.module('myApp', ['LocalStorageModule'])
.config(['localStorageServiceProvider',
function(localStorageServiceProvider) {
localStorageServiceProvider.setPrefix('my-app');
}]);
myApp.factory('myStorage',
//code ommitted
myApp.controller('MyCtrl', [$scope, 'myStorage',
function MyController($scope, myStorage){
}
]);
However, if in the three files, I instead do it this way (without the global) then I get an unknownProvider error in myCtrl
angular.module('myApp', ['LocalStorageModule'])
.config(['localStorageServiceProvider',
function(localStorageServiceProvider) {
localStorageServiceProvider.setPrefix('my-app');
}]);
angular.module('myApp', [])
.factory('myStorage',
//code omitted
angular.module('myApp', [])
.controller('MyCtrl', [$scope, 'myStorage',
function MyController($scope, myStorage){
}
]);
Question: IN the example above, how can I make the storage from the factory available in the controller without using the global variable pattern?
You should only define module once, and use it in rest of the places. Otherwise it gets overwritten. Please remove the dependency array from module definition for factory & controller. Hope that helps.
angular.module('myApp')
.factory('myStorage',
//code omitted
angular.module('myApp')
.controller('MyCtrl', ['$scope', 'myStorage',
function ($scope, myStorage){
}
]);
Also your controller declaration is needs to be corrected as above.
The Best way to inject any service, factory etc... this way reduce Complicity...
`angular.module('myApp')
.factory('myStorage',
//code omitted
angular.module('myApp')
.controller('MyCtrl', myCtrlFun);
myCtrlFun.$inject = ['$scope', 'myStorage'];
function myCtrlFun($scope, myStorage){
}
`

How to separate Controller file in angularjs

I have looked at various examples of separating the files. I can understand them but the problem comes with the way my code is. I want separate these controllers in different files.
'use strict';
angular.module('myModule', ['ui.bootstrap']);
var myApp = angular.module('myApp', []);
myApp.config(['$httpProvider', function ($httpProvider) {
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
}]);
myApp.config(['$routeProvider',
function ($routeProvider) {
$routeProvider.when('/getplaces', {
templateUrl: 'templates/getplaces.html',
controller: 'ListCtrl'
})
The below controller needs to be in a different file.
///////////// MONTHLY DATA /////////////////////////////////////
myApp.config(['$routeProvider', function ($routeProvider) {
$routeProvider.when('/getmonth', {
templateUrl: 'templates/getmacs.html',
controller: 'MonthlyCtrl'
})
}])
.controller('MonthlyCtrl', function ($scope, $http) { $scope.visible = true;
})
I have more than 20 controllers like above. but how do I separate them.
Here is how you should do it,
first declaration
angular.module('appName', ['Module1', 'Module2', 'Service1']);
subsequent declarations
here all the controllers and service can be in separate files.
angular
.module('Module1', [])
.controller('AbcController', ['$scope', '$timeout', 'Service1', function ($scope, $timeout, service1) {} ]);
angular
.module('Module2', [])
.controller('EfgController', ['$scope', '$timeout', 'Service1', function ($scope, $timeout, service1) {} ]);
angular.module('Service1', [])
.service('XYZService', ['$http', function LmnoService($http) {
} ]);
This should easily be done, I would organize my application route configurations into the main app.js file.
myApp.config(['$routeProvider',
function ($routeProvider) {
$routeProvider.when('/getplaces', {
templateUrl: 'templates/getplaces.html',
controller: 'ListCtrl'
}).when('/getmonth', {
templateUrl: 'templates/getmacs.html',
controller: 'MonthlyCtrl'
})
}])
Then when you create a separate controller in each file just reference the application name as such:
myApp.controller('MonthlyCtrl', ['$scope', '$http', function ($scope, $http) {
$scope.visible = true;
}])
You will also notice I am using the array initializer way, this will save you some hastles when you are doing minification.
You can follow this convention:
First load all the library dependencies like angular, angular-routes etc
then your config holder js file which contains your module declaration.
then all other files with controller methods.
I would map specific modules to functionality (and not by layers), each one containing its concerned controllers, services and appropriate directives.
You would have one module called 'places.list' for instance, containing all controllers, services/factories and directives associated to it.
The rule is: one module, one file, otherwise you would be forced to declare those files in order... (first modules declaration..then controllers etc.. ugly)
If you split your modules in the right way, you will notice that each one is easy to maintain and doesn't contain in general a huge amount of code.
Even each route declaration (.config) would be split across those modules.
=> All the route concerning places would be declared inside the module places.list.
Indeed, it would be ugly (and difficult to maintain) to declare the whole navigation rules in your main module..
Thus, each module would be easily testable by loading only specific module's dependencies that are relevant for the test.

How can I inject dependencies into my angular controller neatly?

I have:
app.controller('ReportsCtrl', ['$scope', 'reportsApiCall', 'analyticsInitialiserClient', '$timeout', 'chart', 'originCompositionChart', 'executionTimeChart', 'cacheCompositionChart', function ($scope, reportsApiCall, analyticsInitialiserClient, $timeout, chart, originCompositionChart, executionTimeChart, cacheCompositionChart) {
But I like the syntax of using. myController.$inject = ['$scope','notify'];
But I don't want to declare the name of myController, because then I'm polluting the global namespace. Is there a way I can go: ?
app.controller('ReportsCtrl', function ($scope, reportsApiCall, analyticsInitialiserClient, $timeout, chart, originCompositionChart, executionTimeChart, cacheCompositionChart) {
}).$inject();
Because that syntax is failing for me at the moment :( ?
You could do this:
(function(){
myController.$inject = ['service1','service2'];
function myController(s1,s2){
//controller logic
}
app.controller('myCtrl',myController);
}());
I use grunt-ngmin to annotate my source code when it's minified and just don't place annontations in my code directly.

Resources