Comment créer des fichiers de contrôleur AngularJS séparés?

315

J'ai tous mes contrôleurs AngularJS dans un seul fichier, controllers.js. Ce fichier est structuré comme suit:

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

Ce que j'aimerais faire, c'est mettre Ctrl1 et Ctrl2 dans des fichiers séparés. J'inclurais alors les deux fichiers dans mon index.html, mais comment cela devrait-il être structuré? J'ai essayé de faire quelque chose comme ça et cela lance une erreur dans la console du navigateur Web disant qu'il ne peut pas trouver mes contrôleurs. Des indices?

J'ai recherché StackOverflow et trouvé cette question similaire - cependant, cette syntaxe utilise un framework différent (CoffeeScript) au-dessus d'Angular, et donc je n'ai pas pu suivre.


AngularJS: Comment créer des contrôleurs dans plusieurs fichiers

Beebunny
la source

Réponses:

399

Fichier un:

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

Fichier deux:

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

}]);

Fichier trois:

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

}]);

Inclure dans cet ordre. Je recommande 3 fichiers afin que la déclaration du module soit indépendante.


Quant à la structure des dossiers, il y a beaucoup, beaucoup d'opinions sur le sujet, mais ces deux-là sont plutôt bons

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

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

Fresheyeball
la source
1
Si l'OP indiquait une confusion sur la syntaxe CoffeeScript, peut-être serait-il préférable de ne pas l'utiliser dans votre réponse?
Andrew
3
@Andrew à mon humble avis aide future et faire un dossier des solutions est ce que SO est vraiment tout, pas q et a extemporané.
Fresheyeball
2
@RuslanIsmagilov votre appCtrlest un mondial window.appCtrl. Ce n'est pas une bonne pratique.
Fresheyeball
1
@Fresheyeball, le problème de cette approche est que l'ordre d'importation dans le fichier index.html est important, sinon, erreur d'émission angulaire.
Deoxyseia
2
@hendryau, eh bien je travaillais avec le nom du module présent dans l'OP. Cela dit, certains estiment qu'il est préférable, sur le plan organisationnel, d'avoir plusieurs modules espacés par nom, plutôt qu'un module d'application central.
Fresheyeball
177

L'utilisation de l'API angular.module avec un tableau à la fin indiquera à angular de créer un nouveau module:

myApp.js

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

L'utiliser sans le tableau est en fait une fonction getter. Donc pour séparer vos contrôleurs, vous pouvez faire:

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) {}]);

Pendant vos importations javascript, assurez-vous juste que myApp.js est après AngularJS mais avant tous les contrôleurs / services / etc ... sinon angular ne pourra pas initialiser vos contrôleurs.

Jimmy Au
la source
où dois-je écrire mes dépendances. var myapp = angular.module ('demo', ['ngRoute', 'ngCookies', 'ui.bootstrap', 'nvd3ChartDirectives', 'ui-rangeSlider', 'textAngular', 'angularTreeview']);
vipin
@vipin comme ce que vous avez tapé, mais assurez-vous qu'il est au-dessus de tous les contrôleurs, services, etc. Techniquement, vous n'avez pas besoin de déclarer var myapp = ...; car angulaire le stockera pour vous.
Jimmy Au
@JimmyAu Où sont chargés Ctrl1.js et Ctrl2.js pour que la page puisse l'utiliser? J'ai myApp.js chargé juste après angulaire, mais la page ne trouve pas les contrôleurs. Dois-je les ajouter explicitement en tant que script sur la vue qui en a besoin? Ou dois-je toujours inclure chaque fichier de contrôleur sur chaque page?
Sinaesthetic
2
Merci d'avoir clarifié pourquoi seul le premier appel a besoin de [].
Jim B.
49

Bien que les deux réponses soient techniquement correctes, je veux introduire un choix de syntaxe différent pour cette réponse. Cet imho facilite la lecture de ce qui se passe avec l'injection, la distinction entre etc.

File One

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

Fichier deux

// 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
}

Fichier trois

// 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
}
jason328
la source
Intéressant, cela m'empêche d'aller dans plusieurs fichiers pour enregistrer un contrôleur
mrwaim
4
Je vois beaucoup de codage comme celui-ci. Quel est l'avantage? d'avoir $ inject et une fonction séparée.
Alaksandar Jesus Gene
2
Je crois que cela rend le code plus facile à lire. Je sais exactement ce qui est injecté. Considérez-le comme une «séparation des préoccupations» ligne par ligne.
jason328
2
Un code comme celui-ci produit non seulement un code plus lisible, est beaucoup plus facile à déboguer et réduit la quantité de code de rappel imbriqué (voir github.com/johnpapa/angular-styleguide/blob/master/a1/… )
rfornal
Si je pouvais +1 à ces 1000 fois, je le ferais - bravo!
Dan Chase
17

Et cette solution? Modules et contrôleurs dans les fichiers (à la fin de la page) Il fonctionne avec plusieurs contrôleurs, directives et ainsi de suite:

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 a également une recommandation de meilleures pratiques pour la structure des applications angulaires que j'aime vraiment regrouper par contexte. Pas tous les html dans un dossier, mais par exemple tous les fichiers de connexion (html, css, app.js, controller.js et ainsi de suite). Donc, si je travaille sur un module, toutes les directives sont plus faciles à trouver.

schasoli
la source
3

Par souci de concision, voici un exemple ES2015 qui ne repose pas sur des variables globales

// 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)
Pete TNT
la source
1
Vous pourriez économiser un peu de frappe si vous utilisiez des fonctions nommées .. elles ont des propriétés pratiques name.. vous pouvez donc simplement les utiliser ExampleCtrl.nameau lieu de les dupliquer .. en les tripliquant.
Antti Pihlaja
0

Pas si gracieux, mais la solution d'implémentation très simple - utilisant une variable globale.

Dans le "premier" fichier:


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

dans le "deuxième", "troisième", etc:


myApp.controller('MyController', function($scope) {
    .... 
    }); 
user3682640
la source
-je utiliser ce code mais ne peux toujours pas charger mon contrôleur? il renvoie une erreur: Erreur: [ng: areq] L'argument 'ProductCtrl' n'est pas une fonction, n'est pas défini.
QViet
7
c'est vraiment une mauvaise pratique
Brendan
@Kim Jong Un Vous verrez cette erreur si vous n'ajoutez / concaténez pas le contrôleur au module que vous avez créé. Cela fonctionnera donc si vous utilisez la syntaxe suivante:angular.module('myApp').controller('ProductCtrl', ['$scope', '$http', function($scope, $http){ //Your ProductCtrl code goes here }]);
Devner
1
@Brendan, simplement déclarer que quelque chose est une mauvaise pratique vaut mieux que rien - mais pas beaucoup. Dites-nous pourquoi cette mauvaise pratique aidera les autres.
Mawg dit réintégrer Monica