Come creare file controller AngularJS separati?


315

Ho tutti i miei controller AngularJS in un file, controllers.js. Questo file è strutturato come segue:

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

Quello che mi piacerebbe fare è mettere Ctrl1 e Ctrl2 in file separati. Includerei quindi entrambi i file nel mio index.html, ma come dovrebbe essere strutturato? Ho provato a fare qualcosa del genere e si verifica un errore nella console del browser Web dicendo che non riesce a trovare i miei controller. Qualche suggerimento?

Ho cercato StackOverflow e ho trovato questa domanda simile - tuttavia, questa sintassi sta usando un framework diverso (CoffeeScript) sopra Angular, e quindi non sono stato in grado di seguirlo.


AngularJS: Come posso creare controller in più file

Risposte:


399

File uno:

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

File due:

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

}]);

File tre:

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

}]);

Includi in quell'ordine. Consiglio 3 file, quindi la dichiarazione del modulo è autonoma.


Per quanto riguarda la struttura delle cartelle ci sono molte molte molte opinioni sull'argomento, ma queste due sono piuttosto buone

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

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


1
Se l'OP ha indicato confusione sulla sintassi di CoffeeScript, forse sarebbe meglio non usarlo nella tua risposta?
Andrew

3
@Andrew imho un aiuto futuro e fare un registro delle soluzioni è ciò che SO è davvero tutto, non estemporaneo q e a.
Fresheyeball,

2
@RuslanIsmagilov il tuo appCtrlè un globale window.appCtrl. Questa non è una buona pratica.
Fresheyeball,

1
@Fresheyeball, il problema di questo approccio è che l'ordine di importazione in index.html è importante, altrimenti l'errore di emissione angolare.
Deoxyseia,

2
@hendryau, stavo lavorando con il nome del modulo presente nell'OP. Detto questo, alcuni ritengono che sia meglio dal punto di vista organizzativo, avere più moduli spaziati dal nome, piuttosto che un modulo app centrale.
Fresheyeball,

177

L'uso dell'API angular.module con un array alla fine indica ad Angular di creare un nuovo modulo:

myApp.js

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

Usarlo senza l'array è in realtà una funzione getter. Quindi, per separare i tuoi controller, puoi fare:

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

Durante le tue importazioni JavaScript, assicurati solo che myApp.js sia dopo AngularJS ma prima di qualsiasi controller / servizio / ecc ... altrimenti Angular non sarà in grado di inizializzare i tuoi controller.


dove dovrei scrivere le mie dipendenze. var myapp = angular.module ('demo', ['ngRoute', 'ngCookies', 'ui.bootstrap', 'nvd3ChartDirectives', 'ui-rangeSlider', 'textAngular', 'angularTreeview']);
vipin,

@vipin proprio come quello che hai digitato, ma assicurati che sia al di sopra di qualsiasi controller, servizio, ecc. Tecnicamente non è necessario dichiarare var myapp = ...; perché angolare lo memorizzerà per te.
Jimmy Au,

@JimmyAu Dove vengono caricati Ctrl1.js e Ctrl2.js in modo che la pagina possa utilizzarlo? Ho myApp.js caricato subito dopo angolare, ma la pagina non riesce a trovare i controller. Devo aggiungerli esplicitamente come script nella vista che ne ha bisogno? O devo ancora includere tutti i file del controller in ogni pagina?
Sinaesthetic,

2
Grazie per aver chiarito il motivo per cui solo la prima chiamata richiede [].
Jim B.

49

Sebbene entrambe le risposte siano tecnicamente corrette, voglio introdurre una scelta di sintassi diversa per questa risposta. Questo imho rende più facile leggere cosa sta succedendo con l'iniezione, distinguere tra ecc.

File uno

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

File due

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

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

Interessante, mi impedisce di andare su più file per registrare un controller
mrwaim

4
Vedo un sacco di codice come questo. Qual è il vantaggio? di avere $ inject e una funzione separata.
Alaksandar Jesus Gene,

2
Credo che renda il codice più facile da leggere. So cosa viene iniettato esattamente. Pensalo come una "separazione delle preoccupazioni" su base riga per riga.
jason328,

2
Codice come questo non solo produce un codice più leggibile, è molto più facile da eseguire il debug e riduce la quantità di codice di callback nidificato (vedi github.com/johnpapa/angular-styleguide/blob/master/a1/… )
rfornal

Se potessi fare +1 su questo 1000 volte lo farei - bravo!
Dan Chase,

17

E questa soluzione? Moduli e controller nei file (alla fine della pagina) Funziona con più controller, direttive e così via:

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 ha anche una Raccomandazione sulle migliori pratiche per la struttura dell'app angolare. Mi piace molto raggruppare per contesto. Non tutti gli html in una cartella, ma ad esempio tutti i file per l'accesso (html, css, app.js, controller.js e così via). Quindi, se lavoro su un modulo, tutte le direttive sono più facili da trovare.


3

Per brevità, ecco un esempio ES2015 che non si basa su variabili globali

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

1
Potresti risparmiare un bel po 'di battitura se hai usato funzioni denominate ... hanno proprietà utili name... quindi puoi semplicemente usare ExampleCtrl.nameinvece di dupl .. triplicandolo.
Antti Pihlaja,

0

Non così elegante, ma molto semplice nella soluzione di implementazione - utilizzando la variabile globale.

Nel "primo" file:


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

nel "secondo", "terzo", ecc:


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

uso questo codice ma non riesco ancora a caricare il mio controller? genera errore: Errore: [ng: areq] L'argomento 'ProductCtrl' non è una funzione, non definito.
QViet,

7
questa è davvero una brutta pratica
Brendan,

@Kim Jong Un Vedrai quell'errore se non aggiungi / concateni il controller al modulo che hai creato. Quindi funzionerà se usi la sintassi seguente:angular.module('myApp').controller('ProductCtrl', ['$scope', '$http', function($scope, $http){ //Your ProductCtrl code goes here }]);
Devner

1
@Brendan, affermando semplicemente che qualcosa è cattiva pratica è meglio di niente - ma non molto. Dicci perché è una cattiva pratica aiuterà gli altri.
Mawg dice di ripristinare Monica il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.