ChatGPT解决这个技术问题 Extra ChatGPT

How to create separate AngularJS controller files?

I have all of my AngularJS controllers in one file, controllers.js. This file is structured as follows:

angular.module('myApp.controllers', [])
  .controller('Ctrl1', ['$scope', '$http', function($scope, $http) {    
  }])
  .controller('Ctrl2', ['$scope', '$http', function($scope, $http) }
  }])

What I'd like to do is put Ctrl1 and Ctrl2 into separate files. I would then include both files in my index.html, but how should that be structured? I tried doing some thing like this and it throws an error in the web browser console saying it can't find my controllers. Any hints?

I searched StackOverflow and found this similar question - however, this syntax is using a different framework (CoffeeScript) on top of Angular, and so I haven't been able to follow.

AngularJS: How do I create controllers in multiple files


F
Fresheyeball

File one:

angular.module('myApp.controllers', []);

File two:

angular.module('myApp.controllers').controller('Ctrl1', ['$scope', '$http', function($scope, $http){

}]);

File three:

angular.module('myApp.controllers').controller('Ctrl2', ['$scope', '$http', function($scope, $http){

}]);

Include in that order. I recommend 3 files so the module declaration is on its own.

As for folder structure there are many many many opinions on the subject, but these two are pretty good

https://github.com/angular/angular-seed

http://briantford.com/blog/huuuuuge-angular-apps.html


If the OP indicated confusion about CoffeeScript syntax, maybe it would be best not to use it in your answer?
@Andrew imho future help and making a record of solutions is what SO is really all about, not extemporaneous q and a.
@RuslanIsmagilov your appCtrl is a global window.appCtrl. That is not a good practice.
@Fresheyeball, the problem of this approach is which the order of import in the index.html is important, otherwise, Angular emit error.
@hendryau, well I was working with the module name present in the OP. That said, some feel that its better organizationally, to have multiple name-spaced modules, rather than a central app module.
J
Jimmy Au

Using the angular.module API with an array at the end will tell angular to create a new module:

myApp.js

// It is like saying "create a new module"
angular.module('myApp.controllers', []); // Notice the empty array at the end here

Using it without the array is actually a getter function. So to seperate your controllers, you can do:

Ctrl1.js

// It is just like saying "get this module and create a controller"
angular.module('myApp.controllers').controller('Ctrlr1', ['$scope', '$http', function($scope, $http) {}]);

Ctrl2.js

angular.module('myApp.controllers').controller('Ctrlr2', ['$scope', '$http', function($scope, $http) {}]);

During your javascript imports, just make sure myApp.js is after AngularJS but before any controllers / services / etc...otherwise angular won't be able to initialize your controllers.


where should i write my dependencies. var myapp = angular.module('demo', ['ngRoute','ngCookies','ui.bootstrap','nvd3ChartDirectives','ui-rangeSlider','textAngular','angularTreeview']);
@vipin just like what you've typed, but make sure it's above any controllers, services, etc. Technically you don't need to declare var myapp = ...; because angular will store it for you.
@JimmyAu Where does Ctrl1.js and Ctrl2.js get loaded so that the page can use it? I have myApp.js loaded just after angular, but the page can't find the controllers. Do I have to explicitly add them as a script on the view that needs it? Or do I still have to include every controller file on every page?
Thanks for clarifying why only the first call needs [].
t
thank_you

Although both answers are technically correct, I want to introduce a different syntax choice for this answer. This imho makes it easier to read what's going on with injection, differentiate between etc.

File One

// Create the module that deals with controllers
angular.module('myApp.controllers', []);

File Two

// Here we get the module we created in file one
angular.module('myApp.controllers')

// We are adding a function called Ctrl1
// to the module we got in the line above
.controller('Ctrl1', Ctrl1);

// Inject my dependencies
Ctrl1.$inject = ['$scope', '$http'];

// Now create our controller function with all necessary logic
function Ctrl1($scope, $http) {
  // Logic here
}

File Three

// Here we get the module we created in file one
angular.module('myApp.controllers')

// We are adding a function called Ctrl2
// to the module we got in the line above
.controller('Ctrl2', Ctrl2);

// Inject my dependencies
Ctrl2.$inject = ['$scope', '$http'];

// Now create our controller function with all necessary logic
function Ctrl2($scope, $http) {
  // Logic here
}

Interesting, it does keep me from going to multiple files to register a controller
I see a lots of coding like this. What is the advantage? of having $inject and a function seperate.
I believe it makes the code easier to read. I know what exactly is being injected. Think of it as a "separation of concerns" on a line-by-line basis.
Code like this not only produces more readable code, is much easier to debug, and reduces the amount of nested callback code (see github.com/johnpapa/angular-styleguide/blob/master/a1/…)
If I could +1 this 1000 times I would - bravo!
A
Ahmed Mansour

What about this solution? Modules and Controllers in Files (at the end of the page) It works with multiple controllers, directives and so on:

app.js

var app = angular.module("myApp", ['deps']);

myCtrl.js

app.controller("myCtrl", function($scope) { ..});

html

<script src="app.js"></script>
<script src="myCtrl.js"></script>
<div ng-app="myApp" ng-controller="myCtrl">

Google has also a Best Practice Recommendations for Angular App Structure I really like to group by context. Not all the html in one folder, but for example all files for login (html, css, app.js,controller.js and so on). So if I work on a module, all the directives are easier to find.


P
Pete TNT

For brevity, here's an ES2015 sample that doesn't rely on global variables

// controllers/example-controller.js

export const ExampleControllerName = "ExampleController"
export const ExampleController = ($scope) => {
  // something... 
}

// controllers/another-controller.js

export const AnotherControllerName = "AnotherController"
export const AnotherController = ($scope) => {
  // functionality... 
}

// app.js

import angular from "angular";

import {
  ExampleControllerName,
  ExampleController
} = "./controllers/example-controller";

import {
  AnotherControllerName,
  AnotherController
} = "./controllers/another-controller";

angular.module("myApp", [/* deps */])
  .controller(ExampleControllerName, ExampleController)
  .controller(AnotherControllerName, AnotherController)

You could save quite bit of typing if you used named functions.. they have handy property name.. so you can simply use ExampleCtrl.name instead of dupl.. triplicating it.
I cannot make it work. plnkr.co/edit/… - Module 'myApp' is not available!
u
user3682640

Not so graceful, but the very much simple in implementation solution - using global variable.

In the "first" file:


window.myApp = angular.module("myApp", [])
....

in the "second" , "third", etc:


myApp.controller('MyController', function($scope) {
    .... 
    }); 

i use this code but still cannot load my controller ? it throw error: Error: [ng:areq] Argument 'ProductCtrl' is not a function, got undefined.
this is really bad practice
@Kim Jong Un You will see that error if you don't add/concatenate the controller to the module that you created. So it will work if you use the following syntax: angular.module('myApp').controller('ProductCtrl', ['$scope', '$http', function($scope, $http){ //Your ProductCtrl code goes here }]);
@Brendan, simply stating that something is bad practise is better than nothing - but not much. Tell us why it is bad practise will help others.