最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How can I have multiple controller files? - Stack Overflow

programmeradmin2浏览0评论

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
Add a ment  | 

5 Answers 5

Reset to default 6

You 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')
发布评论

评论列表(0)

  1. 暂无评论