Wie erstelle ich separate AngularJS-Controller-Dateien?

315

Ich habe alle meine AngularJS-Controller in einer Datei, controller.js. Diese Datei ist wie folgt aufgebaut:

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

Ich möchte Strg1 und Strg2 in separate Dateien einfügen. Ich würde dann beide Dateien in meine index.html aufnehmen, aber wie sollte das strukturiert sein? Ich habe versucht, so etwas zu tun, und es wird ein Fehler in der Webbrowser-Konsole ausgegeben, der besagt, dass meine Controller nicht gefunden werden können. Irgendwelche Hinweise?

Ich habe StackOverflow durchsucht und diese ähnliche Frage gefunden. Diese Syntax verwendet jedoch ein anderes Framework (CoffeeScript) als Angular, sodass ich nicht folgen konnte.


AngularJS: Wie erstelle ich Controller in mehreren Dateien?

Beebunny
quelle

Antworten:

399

Datei eins:

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

Datei zwei:

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

}]);

Datei drei:

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

}]);

In diese Reihenfolge aufnehmen. Ich empfehle 3 Dateien, damit die Moduldeklaration eigenständig ist.


Was die Ordnerstruktur betrifft, gibt es viele, viele Meinungen zu diesem Thema, aber diese beiden sind ziemlich gut

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

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

Fresheyeball
quelle
1
Wenn das OP Verwirrung über die CoffeeScript-Syntax anzeigt, ist es vielleicht am besten, sie nicht in Ihrer Antwort zu verwenden?
Andrew
3
@ Andrew imho zukünftige Hilfe und das Aufzeichnen von Lösungen ist das, worum es bei SO wirklich geht, nicht um unzeitgemäße Fragen und Antworten.
Fresheyeball
2
@ RuslanIsmagilov Ihr appCtrlist ein globaler window.appCtrl. Das ist keine gute Praxis.
Fresheyeball
1
@Fresheyeball, das Problem dieses Ansatzes ist, dass die Reihenfolge des Imports in der index.html wichtig ist, andernfalls Angular-Ausgabefehler.
Deoxyseia
2
@ Hendryau, nun, ich habe mit dem im OP vorhandenen Modulnamen gearbeitet. Einige sind jedoch der Meinung, dass es organisatorisch besser ist, mehrere Module mit Namensabstand zu haben, als ein zentrales App-Modul.
Fresheyeball
177

Wenn Sie die Angular.module-API mit einem Array am Ende verwenden, wird Angular angewiesen , ein neues Modul zu erstellen:

myApp.js

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

Die Verwendung ohne das Array ist eigentlich eine Getter-Funktion. Um Ihre Controller zu trennen, können Sie Folgendes tun:

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

Stellen Sie beim Importieren von Javascript sicher, dass sich myApp.js nach AngularJS befindet, jedoch vor Controllern / Diensten / etc ... andernfalls kann Angular Ihre Controller nicht initialisieren.

Jimmy Au
quelle
Wo soll ich meine Abhängigkeiten schreiben? var myapp = angle.module ('demo', ['ngRoute', 'ngCookies', 'ui.bootstrap', 'nvd3ChartDirectives', 'ui-rangeSlider', 'textAngular', 'angularTreeview']);
Vipin
@vipin genau wie das, was Sie eingegeben haben, aber stellen Sie sicher, dass es über allen Controllern, Diensten usw. steht. Technisch müssen Sie var myapp = ... nicht deklarieren. weil eckig es für Sie speichern wird.
Jimmy Au
@JimmyAu Wo werden Ctrl1.js und Ctrl2.js geladen, damit die Seite es verwenden kann? Ich habe myApp.js direkt nach dem Winkel geladen, aber die Seite kann die Controller nicht finden. Muss ich sie explizit als Skript in der Ansicht hinzufügen, die sie benötigt? Oder muss ich trotzdem jede Controller-Datei auf jeder Seite einfügen?
Sinaesthetic
2
Vielen Dank für die Klarstellung, warum nur der erste Anruf [] benötigt.
Jim B.
49

Obwohl beide Antworten technisch korrekt sind, möchte ich für diese Antwort eine andere Syntaxauswahl einführen. Dieses Imho macht es einfacher zu lesen, was mit der Injektion los ist, zwischen zu unterscheiden usw.

Datei Eins

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

Datei Zwei

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

Datei Drei

// 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
quelle
Interessant, es hält mich davon ab, zu mehreren Dateien zu gehen, um einen Controller zu registrieren
mrwaim
4
Ich sehe eine Menge solcher Codierungen. Was ist der Vorteil? $ injizieren und eine Funktion getrennt haben.
Alaksandar Jesus Gene
2
Ich glaube, es macht den Code leichter zu lesen. Ich weiß, was genau injiziert wird. Stellen Sie sich das als "Trennung von Bedenken" von Zeile zu Zeile vor.
Jason328
2
Code wie dieser erzeugt nicht nur besser lesbaren Code, ist auch viel einfacher zu debuggen und reduziert die Menge an verschachteltem Rückrufcode (siehe github.com/johnpapa/angular-styleguide/blob/master/a1/… )
am
Wenn ich dies 1000 Mal +1 könnte, würde ich - Bravo!
Dan Chase
17

Was ist mit dieser Lösung? Module und Controller in Dateien (am Ende der Seite) Es funktioniert mit mehreren Controllern, Direktiven usw.:

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 hat auch Best-Practice-Empfehlungen für die Angular-App-Struktur, die ich sehr gerne nach Kontext gruppiere. Nicht alle HTML-Dateien in einem Ordner, aber zum Beispiel alle Dateien für die Anmeldung (HTML, CSS, app.js, controller.js usw.). Wenn ich also an einem Modul arbeite, sind alle Anweisungen leichter zu finden.

schasoli
quelle
3

Der Kürze halber hier ein ES2015-Beispiel, das nicht auf globalen Variablen basiert

// 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
quelle
1
Sie könnten einiges an Eingabe sparen, wenn Sie benannte Funktionen verwenden würden. Sie haben praktische Eigenschaften name. Sie können sie also einfach verwenden, ExampleCtrl.nameanstatt sie zu duplizieren.
Antti Pihlaja
0

Nicht so anmutig, aber die sehr einfach zu implementierende Lösung - mit globalen Variablen.

In der "ersten" Datei:


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

im "zweiten", "dritten" usw.:


myApp.controller('MyController', function($scope) {
    .... 
    }); 
user3682640
quelle
Ich verwende diesen Code, kann meinen Controller aber immer noch nicht laden. es wirft Fehler: Fehler: [ng: areq] Argument 'ProductCtrl' ist keine Funktion, wurde undefiniert.
QViet
7
Das ist wirklich eine schlechte Übung
Brendan
@Kim Jong Un Dieser Fehler wird angezeigt, wenn Sie den Controller nicht zu dem von Ihnen erstellten Modul hinzufügen / verketten. Es wird also funktionieren, wenn Sie die folgende Syntax verwenden:angular.module('myApp').controller('ProductCtrl', ['$scope', '$http', function($scope, $http){ //Your ProductCtrl code goes here }]);
Devner
1
@Brendan, einfach zu sagen, dass etwas schlechte Praxis ist, ist besser als nichts - aber nicht viel. Sagen Sie uns, warum schlechte Praktiken anderen helfen.
Mawg sagt, Monica