SOLVED
So after viewing your responses and making minor changes to my code, I found a simple typo which prevented me to reach the result I was after. So thank you all to helping with where I was going wrong, I've now got the controllers seperated and everything's working as planned!
----
I am currently developing a hybrid mobile application using Cordova, Ionic and AngularJS within Visual Studio 2015. Due to the vast amount of code I have in my single controller.js file, I want to separate the code so I have a .js controller file per template; instead of everything in one file. Unfortunately, I I do not understand how to pull this off (learning AngularJS still). I've done some researched but the majority of examples I have seen show a very simple demo, which I replicate with my own code but it still doesn't work. So I was hoping if someone can give me an insight where I may be going wrong.
File Structure in /www
- index.html
/js
app.js
controllers.js
/js/controllers
login.js
sales.js
/templates
login.html
sales.html
/js/app .js
angular.module('main', ['ionic', 'main.controllers', 'chart.js', 'ngCordova', 'ngIOS9UIWebViewPatch', 'angular.filter'])
.config(function ($stateProvider, $urlRouterProvider, $ionicConfigProvider) {
$stateProvider
.state('login', {
cache: false,
url: "/login",
templateUrl: "templates/login.html",
controller: "LoginCtrl"
})
.state('sales', {
cache: false,
url: "/sales",
templateUrl: "templates/sales.html",
controller: "SalesCtrl"
})
$urlRouterProvider.otherwise('/login')
$ionicConfigProvider.views.swipeBackEnabled(false);
});
/js/controllers.js
angular.module('main.controllers', ['ionic', 'ngCordova']);
/js/controllers/login.js
angular.module('main.controllers', [])
.controller("LoginCtrl", function ($scope, $state, $cordovaSQLite, $timeout, $ionicPopup, $cordovaDevice, $ionicLoading, $cordovaKeyboard, $cordovaToast) {
$ionicLoading.show({
template: 'Loading...'
});
// DO STUFF
/js/controllers/sales/js
angular.module('main.controllers', [])
.controller("SalesCtrl", function ($scope, $state, $http, $ionicLoading, $cordovaSQLite, $cordovaToast) {
$ionicLoading.show({
template: 'Loading data...'
});
// DO STUFF
Following this structure, I get this error (quote below): ;p1=not%20a%20function,%20got%20undefined
Argument 'LoginCtrl' is not a function, got undefined
I managed to get it to work slightly, only when I had login.js and not sales.js, but of course $state.* stopped working when trying to change template. So I know that wasn't 100% either. Hopefully this will make sense, fi it doesn't just clarify what I may be not making sense in, and I shall explain more if need be, appreciate any help. :)
EDIT
index.html
<!-- App references -->
<link href="css/ionic.css" rel="stylesheet" />
<link href="css/angular-chart.css" rel="stylesheet" />
<link href="css/index.css" rel="stylesheet" />
<script src="lib/ionic/ionic.bundle.js"></script>
<script src="lib/ngCordova/ng-cordova.js"></script> <!-- Must be after Ionic but before Cordova-->
<script src="cordova.js"></script>
<script src="scripts/index.js"></script>
<script src="lib/angular-cookies/angular-cookies.min.js"></script>
<script src="lib/angular-chart/Chart.min.js"></script>
<script src="lib/angular-chart/angular-chart.min.js"></script>
<script src="lib/angular-ios9-uiwebview.patch.js"></script>
<script src="lib/angular-filter/angular-filter.min.js"></script>
<script src="js/directives/favourite.js"></script>
<script src="js/controllers.js"></script>
<script src="js/controllers/login.js"></script>
<script src="js/controllers/sales.js"></script>
<script src="js/app.js"></script>
SOLVED
So after viewing your responses and making minor changes to my code, I found a simple typo which prevented me to reach the result I was after. So thank you all to helping with where I was going wrong, I've now got the controllers seperated and everything's working as planned!
----
I am currently developing a hybrid mobile application using Cordova, Ionic and AngularJS within Visual Studio 2015. Due to the vast amount of code I have in my single controller.js file, I want to separate the code so I have a .js controller file per template; instead of everything in one file. Unfortunately, I I do not understand how to pull this off (learning AngularJS still). I've done some researched but the majority of examples I have seen show a very simple demo, which I replicate with my own code but it still doesn't work. So I was hoping if someone can give me an insight where I may be going wrong.
File Structure in /www
- index.html
/js
app.js
controllers.js
/js/controllers
login.js
sales.js
/templates
login.html
sales.html
/js/app .js
angular.module('main', ['ionic', 'main.controllers', 'chart.js', 'ngCordova', 'ngIOS9UIWebViewPatch', 'angular.filter'])
.config(function ($stateProvider, $urlRouterProvider, $ionicConfigProvider) {
$stateProvider
.state('login', {
cache: false,
url: "/login",
templateUrl: "templates/login.html",
controller: "LoginCtrl"
})
.state('sales', {
cache: false,
url: "/sales",
templateUrl: "templates/sales.html",
controller: "SalesCtrl"
})
$urlRouterProvider.otherwise('/login')
$ionicConfigProvider.views.swipeBackEnabled(false);
});
/js/controllers.js
angular.module('main.controllers', ['ionic', 'ngCordova']);
/js/controllers/login.js
angular.module('main.controllers', [])
.controller("LoginCtrl", function ($scope, $state, $cordovaSQLite, $timeout, $ionicPopup, $cordovaDevice, $ionicLoading, $cordovaKeyboard, $cordovaToast) {
$ionicLoading.show({
template: 'Loading...'
});
// DO STUFF
/js/controllers/sales/js
angular.module('main.controllers', [])
.controller("SalesCtrl", function ($scope, $state, $http, $ionicLoading, $cordovaSQLite, $cordovaToast) {
$ionicLoading.show({
template: 'Loading data...'
});
// DO STUFF
Following this structure, I get this error (quote below): https://docs.angularjs/error/ng/areq?p0=LoginCtrl&p1=not%20a%20function,%20got%20undefined
Argument 'LoginCtrl' is not a function, got undefined
I managed to get it to work slightly, only when I had login.js and not sales.js, but of course $state.* stopped working when trying to change template. So I know that wasn't 100% either. Hopefully this will make sense, fi it doesn't just clarify what I may be not making sense in, and I shall explain more if need be, appreciate any help. :)
EDIT
index.html
<!-- App references -->
<link href="css/ionic.css" rel="stylesheet" />
<link href="css/angular-chart.css" rel="stylesheet" />
<link href="css/index.css" rel="stylesheet" />
<script src="lib/ionic/ionic.bundle.js"></script>
<script src="lib/ngCordova/ng-cordova.js"></script> <!-- Must be after Ionic but before Cordova-->
<script src="cordova.js"></script>
<script src="scripts/index.js"></script>
<script src="lib/angular-cookies/angular-cookies.min.js"></script>
<script src="lib/angular-chart/Chart.min.js"></script>
<script src="lib/angular-chart/angular-chart.min.js"></script>
<script src="lib/angular-ios9-uiwebview.patch.js"></script>
<script src="lib/angular-filter/angular-filter.min.js"></script>
<script src="js/directives/favourite.js"></script>
<script src="js/controllers.js"></script>
<script src="js/controllers/login.js"></script>
<script src="js/controllers/sales.js"></script>
<script src="js/app.js"></script>
Share
Improve this question
edited Dec 21, 2015 at 19:38
Pankaj Parkar
136k23 gold badges240 silver badges303 bronze badges
asked Dec 21, 2015 at 15:04
MattVonMattVon
5211 gold badge8 silver badges26 bronze badges
2
- how do you include your javascript files in your main html file? – Raphael Müller Commented Dec 21, 2015 at 15:26
- @RaphaelMüller, updated my post at the bottom to show. All that is in my <head> tag. – MattVon Commented Dec 21, 2015 at 15:31
5 Answers
Reset to default 6You are redefining your module again & again in your each controller file. Which is clearing out old registered controller from that module.
You have already defined that module in your /js/controllers.js
.
angular.module('main.controllers', ['ionic', 'ngCordova']);
So reuse that module in other Javascript files when your are binding any ponent to it as below.
angular.module('main.controllers')
The best approach is that you clearly separate module creation from module usage.
modules.js:
angular.module('main', ['main.sales']);
angular.module('main.sales', []);
src/sales/scripts/sales-controller.js:
angular.module('main.sales').controller(function() {});
If you concat and minify your js files via grunt or gulp, you should always explicitly include modules.js first, afterwards you can include the rest via a pattern like 'src/**/*.js' for example.
This way the modules are always defined before they are used. If that's not the case, angular will plain about a non existing module.
PS: it's way better to create functional modules (sales related functionality in 1 module) instead of technical modules (all controllers in 1 module)
You are declaring the main.controllers
module twice, once for each controller. Also, it's not strictly required to declare a separate module for the controllers, you could just declare the controllers within your main module. Some would argue that you lose reusability - and they would be right - but depending on the size of your project and how tightly coupled your controllers are with your application (90% of the time the answer is: very) you could go that way. Since you are probably just starting out, try doing something like this:
js/app.js
angular.module('main', ['ionic', 'chart.js', 'ngCordova', 'ngIOS9UIWebViewPatch', 'angular.filter'])
.config(function ($stateProvider, $urlRouterProvider, $ionicConfigProvider) {
$stateProvider
.state('login', {
cache: false,
url: "/login",
templateUrl: "templates/login.html",
controller: "LoginCtrl"
})
.state('sales', {
cache: false,
url: "/sales",
templateUrl: "templates/sales.html",
controller: "SalesCtrl"
})
$urlRouterProvider.otherwise('/login')
$ionicConfigProvider.views.swipeBackEnabled(false);
});
Note that I am no longer depending on main.controllers
? That's because next I'm doing this:
angular.module('main')
.controller("LoginCtrl", function ($scope, $state, $cordovaSQLite, $timeout, $ionicPopup, $cordovaDevice, $ionicLoading, $cordovaKeyboard, $cordovaToast) {
$ionicLoading.show({
template: 'Loading...'
});
// DO STUFF
And this:
angular.module('main')
.controller("SalesCtrl", function ($scope, $state, $http, $ionicLoading, $cordovaSQLite, $cordovaToast) {
$ionicLoading.show({
template: 'Loading data...'
});
// DO STUFF
The different controllers can (and should) be declared each in a separate file, so that you have a clear structure. It might be more correct to have a separate module for the controllers, and I fear my opinion might be unpopular, but I don't really see the point - whereas I strongly urge you to separate your services and your directives into different modules, since it's much more likely that you're going to use them again in other projects.
My suggest we will organize code by split to the module, and inject it in the app.js file
This is detail my way: https://mymai91.github.io/ionic/2016/07/01/ionic-structure-code-for-project.html
Code demo: https://github./mymai91/mymaiApp
to anyone looking at the "solved code"... The Square brackets in the inner controlleres should be removed:
angular.module('main.controllers', [])
-->
angular.module('main.controllers')