Is it possible to utilize multiple controller files?

SOLVED

After reviewing your feedback and making some adjustments to my code, I discovered a simple typo that was preventing me from achieving the desired result. Big thanks to everyone who assisted in pinpointing where I was going wrong. I've successfully separated the controllers now, and everything is functioning as intended!

----

I am currently working on developing a hybrid mobile application using Cordova, Ionic, and AngularJS within Visual Studio 2015. Due to the extensive amount of code in my single controller.js file, I have decided to separate the code so that each template has its own .js controller file instead of having everything in one file. However, I am still learning AngularJS and struggling to execute this task. Despite researching and trying out various examples, I haven't been successful yet. So, I'm hoping for some insight into where I might 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

With this structure in place, I encountered the following error (quoted below): https://docs.angularjs.org/error/ng/areq?p0=LoginCtrl&p1=not%20a%20function,%20got%20undefined

Argument 'LoginCtrl' is not a function, got undefined

I managed to make it partially work when I had login.js but no sales.js, however, the $state.* functionality stopped working when attempting to change templates. So, I understand that wasn't a complete solution either. If this is unclear, please let me know what part doesn't make sense, and I'll provide further clarification. Appreciate any assistance! :)

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>

Answer №1

Stop repeating the definition of your module in every controller file. This is causing the old registered controllers to be cleared out from the module.

You have already declared the module in /js/controllers.js.

angular.module('main.controllers', ['ionic', 'ngCordova']);

Instead, simply refer back to that existing module in other JavaScript files when binding components to it like this:

angular.module('main.controllers')

Answer №2

To ensure proper organization, it is essential to clearly distinguish 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() {});

When concatenating and minifying js files using grunt or gulp, remember to always include modules.js first, followed by the rest using a pattern such as 'src/**/*.js'.

This approach guarantees that the modules are defined before they are utilized. Failure to do so may result in angular throwing an error about a missing module.

Additionally, it's advisable to create functional modules (combining sales-related functionality into one module) rather than technical modules (placing all controllers in one module).

Answer №3

Instead of declaring the main.controllers module twice for each controller, consider incorporating the controllers within your main module. While some argue that this may limit reusability, depending on the project size and controller-application coupling, it could be a viable option. For beginners, try structuring your code 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);
});

You can see that I no longer depend on main.controllers. Here's how I proceed:

angular.module('main')
.controller("LoginCtrl", function ($scope, $state, $cordovaSQLite, $timeout,       $ionicPopup, $cordovaDevice, $ionicLoading, $cordovaKeyboard, $cordovaToast) {
$ionicLoading.show({
    template: 'Loading...'
});
// DO STUFF

And also:

angular.module('main')
.controller("SalesCtrl", function ($scope, $state, $http, $ionicLoading, $cordovaSQLite, $cordovaToast) {
$ionicLoading.show({
    template: 'Loading data...'
});
// DO STUFF

Organize each controller in a separate file for clarity. While some suggest having a separate module for controllers, it may not be necessary compared to separating services and directives into different modules for better future reuse.

Answer №4

My suggestion is to organize the code by splitting it into modules and then injecting it into the app.js file.

You can find more details on my approach here:

For a code demonstration, check out: https://github.com/mymai91/mymaiApp

Answer №5

for those reviewing the "resolved code"... It is advised to eliminate the square brackets within the internal controllers:

angular.module('main.controllers', [])

-->

angular.module('main.controllers')

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Exploring the Art of Structuring Json Data Using jquery

After importing data from a csv file, I am trying to utilize it in a dependent dropdown feature using jquery. However, I am unsure if it is feasible to nest the received data with my current code implementation. CSV File Banco Tarjeta Cuotas Medio_Pag ...

Having trouble setting a JavaScript variable with a PHP session variable

In my PHP file, I have a session variable named $_SESSION['SESS_USER_TYPE'] set to a 2-character string. After the PHP script redirects to an HTML file, I need to retrieve this session variable in a JavaScript variable. This is how I am attempti ...

dual slider controls on a single webpage

I am attempting to place two different sliders on the same page. When I implement the following code for one slider, it functions correctly: <h3>Strength of Belief</h3> <div class="slidecontainer"> <div class="slider_left"> < ...

What is the best way to extract a value from a string containing a list of maps?

I am currently facing a requirement where I need to extract values from a map in the following format: "{xyz=True, abc=asd-1123, uvw=null}" The challenge is to retrieve these values from a string representation of the map. I have attempted usi ...

Tips on changing the outline color by clicking

I'm working on a simple code where I need to change the outline color when a user clicks on a text field. <input type="text" id="box1" /> <input type="password" id="box2" /> <input type="email" id="box3" /> <input type="submit" ...

What causes the discrepancy in time between a node.js server and mongodb?

I have a document in my mongoDB database with an attribute 'dia' that is a Date set to: 'ISODate("2018-09-07T20:00:00.000Z")' An issue arises when attempting to retrieve this document in my node.js server. I am currently using mongo ...

How do I make the message "document.getElementById(...) is null" become true?

When running my code, only two of the document.getElementById calls (ctx1 and ctx2) successfully get values while the others (such as ctx3) do not. How can I ensure that all elements retrieve their values without receiving an error message? Below is a snip ...

What is the reason for the inconsistency in CORS post requests working for one scenario but not the other?

Currently, I am facing an issue while attempting to add email addresses to a mailchimp account and simultaneously performing other tasks using JavaScript once the email is captured. Here's the snippet of my JavaScript code: function addEmail(){ v ...

Is there a way to use jQuery to automatically make a field stand out visually?

I am looking for a way to make a text field automatically underline as the user types. The line should follow along with the characters in real-time, and when the user moves away from the field, I want the line to fill up the entire width. This signifies t ...

php executing javascript - error

I have a question regarding my PHP file code: echo '<script type="text/javascript">'; echo '<audio id="player" src="../cdh/ba1.mp3"></audio>'; echo '<a onclick="document.getElementById( ...

Using jQuery to emphasize search text in a user-friendly manner

After successfully implementing a search function for a table, I faced the challenge of highlighting the search keyword within a cell. Despite searching for a solution online, I couldn't find anything useful! Here is my HTML code: <table class="s ...

What is the best way to determine if an application has been installed on an Android device while browsing a website?

Let's set the scene: I've got a website that needs to use JavaScript to determine whether my app is already installed on the android device it's currently being used on. If the app is installed, the page will display a link (with a custom ...

"Customize your text alignment with TinyMCE's align

I'm in the process of updating from an outdated version of TinyMCE to the most recent release. In the old TinyMCE, if you inserted an image and aligned it to the left, the HTML generated looked like this: < img src="testing.jpg" align="left" > ...

The HTTP request seems to be malfunctioning

When attempting to establish a connection and retrieve data from a PHP file using an AJAX request, it's important to note that the AJAX JS is located on a different website. Here is the script being used: var quer; try { quer = new XMLHttpRequest( ...

Synchronization-free API and callback functions

I am in need of utilizing an asynchronous service. My current approach involves sending data to this service using PHP and CURL, as well as receiving data from a URL provided by the service. How can I effectively respond or wait for feedback from this serv ...

Issue encountered while attempting to host an ejs file using Express in Node.js

I'm encountering an issue while attempting to serve an .ejs file using express. The error I'm getting is as follows: Error: No default engine was specified and no extension was provided. at new View (C:\development\dashboard& ...

Exploring the functionality of the JavaScript switch statement across various condition scenarios

switch (true) { case (angle<20): console.log("case1") break; case (angle<70): console.log("case2") break; case (angle< ...

"Troubleshooting the inconsistency of GraphQL resolver context functionality between Playground and the client in the official NextJS starter

Currently, I am making adjustments to my NextJS/Apollo application to enable SSG with GraphQL API routes. I have referenced this official NextJS starter example as a foundation for configuring the client. An issue arose in my application which led me to g ...

Different JQuery countdowns in an iteration using Django

I'm in the process of developing a sports app using Django. One of the key features I want to include is the ability to display a list of upcoming matches with a countdown timer for each match. Currently, I have managed to implement a single countdow ...

The Signature Pad loses its focus

My HTML code is using JavaScript with Bootstrap and the Signature Pad. The issue I am facing is related to the Bootstrap Collapse feature. When I set the first panel as default, the Signature Pad does not allow me to sign. However, if I set the third panel ...