Jak utworzyć osobne pliki kontrolera AngularJS?

315

Mam wszystkie moje kontrolery AngularJS w jednym pliku, kontrolery.js. Plik ten ma następującą strukturę:

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

Chciałbym umieścić Ctrl1 i Ctrl2 w osobnych plikach. W takim razie dołączałbym oba pliki do pliku index.html, ale jak należy to uporządkować? Próbowałem zrobić coś takiego, co powoduje błąd w konsoli przeglądarki internetowej, mówiąc, że nie można znaleźć moich kontrolerów. Jakieś wskazówki?

Przeszukałem StackOverflow i znalazłem podobne pytanie - jednak ta składnia używa innej struktury (CoffeeScript) na Angularu, więc nie byłem w stanie tego śledzić.


AngularJS: Jak utworzyć kontrolery w wielu plikach

Beebunny
źródło

Odpowiedzi:

399

Plik pierwszy:

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

Plik drugi:

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

}]);

Plik trzeci:

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

}]);

Uwzględnij w tej kolejności. Polecam 3 pliki, aby deklaracja modułu była samodzielna.


Jeśli chodzi o strukturę folderów, istnieje wiele, wiele opinii na ten temat, ale te dwa są całkiem dobre

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

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

Fresheyeball
źródło
1
Jeśli OP wskaże zamieszanie na temat składni CoffeeScript, może lepiej nie używać go w swojej odpowiedzi?
Andrew
3
@Andrew imho przyszła pomoc i rejestrowanie rozwiązań jest tym, o co naprawdę chodzi w SO, a nie doraźne pytania i odpowiedzi.
Fresheyeball,
2
@RuslanIsmagilov twój appCtrljest globalny window.appCtrl. To nie jest dobra praktyka.
Fresheyeball
1
@Fresheyeball, problemem tego podejścia jest to, która kolejność importu w pliku index.html jest ważna, w przeciwnym razie Angular wyemituje błąd.
Deoxyseia,
2
@hendryau, dobrze pracowałem z nazwą modułu obecną w OP. To powiedziawszy, niektórzy uważają, że lepiej organizacyjnie mieć wiele modułów z odstępami między nazwami niż centralny moduł aplikacji.
Fresheyeball
177

Użycie interfejsu API angular.module z tablicą na końcu powie angularowi utworzenie nowego modułu:

myApp.js

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

Używanie go bez tablicy jest właściwie funkcją gettera. Aby oddzielić kontrolery, możesz:

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

Podczas importowania javascript upewnij się, że myApp.js jest po AngularJS, ale przed wszystkimi kontrolerami / usługami itp. ... inaczej Angular nie będzie w stanie zainicjować twoich kontrolerów.

Jimmy Au
źródło
gdzie mam napisać moje zależności. var myapp = angular.module („demo”, [„ngRoute”, „ngCookies”, „ui.bootstrap”, „nvd3ChartDirectives”, „ui-rangeSlider”, „textAngular”, „angularTreeview”]);
vipin
@vipin dokładnie tak, jak wpisałeś, ale upewnij się, że znajduje się ponad wszelkimi kontrolerami, usługami itp. Technicznie nie musisz deklarować var ​​myapp = ...; ponieważ kątowy zapisze go dla ciebie.
Jimmy Au
@JimmyAu Gdzie ładuje się Ctrl1.js i Ctrl2.js, aby strona mogła z niego korzystać? Mam plik myApp.js załadowany tuż po kanciastości, ale strona nie może znaleźć kontrolerów. Czy muszę jawnie dodać je jako skrypt w widoku, który tego potrzebuje? Czy nadal muszę dołączać każdy plik kontrolera na każdej stronie?
Sinaesthetic
2
Dziękujemy za wyjaśnienie, dlaczego potrzebuje tylko pierwsze połączenie [].
Jim B.
49

Chociaż obie odpowiedzi są technicznie poprawne, chcę wprowadzić inny wybór składni dla tej odpowiedzi. To imho ułatwia czytanie, co się dzieje z zastrzykiem, rozróżnianie itp.

Plik pierwszy

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

Plik drugi

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

Plik trzeci

// 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
źródło
Interesujące, nie pozwala mi przechodzić do wielu plików, aby zarejestrować kontroler
mrwaim,
4
Widzę dużo takiego kodowania. Jaka jest zaleta? posiadania $ inject i funkcji osobno.
Alaksandar Jesus Gene
2
Uważam, że dzięki temu kod jest łatwiejszy do odczytania. Wiem, co dokładnie jest wstrzykiwane. Pomyśl o tym jako o „oddzieleniu obaw” w poszczególnych liniach.
jason328
2
Taki kod nie tylko tworzy bardziej czytelny kod, jest znacznie łatwiejszy do debugowania i zmniejsza ilość zagnieżdżonego kodu wywołania zwrotnego (patrz github.com/johnpapa/angular-styleguide/blob/master/a1/... )
rfornal
Gdybym mógł dać +1 1000 razy, zrobiłbym to - brawo!
Dan Chase
17

Co z tym rozwiązaniem? Moduły i kontrolery w plikach (na końcu strony) Działa z wieloma kontrolerami, dyrektywami i tak dalej:

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 ma również zalecenia dotyczące najlepszych praktyk dotyczących struktury aplikacji Angular, które bardzo lubię grupować według kontekstu. Nie wszystkie pliki HTML w jednym folderze, ale na przykład wszystkie pliki do logowania (HTML, CSS, App.js, Controller.js i tak dalej). Więc jeśli pracuję nad modułem, łatwiej jest znaleźć wszystkie dyrektywy.

schasoli
źródło
3

Dla zwięzłości, oto próbka ES2015, która nie opiera się na zmiennych globalnych

// 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
źródło
1
Możesz zaoszczędzić sporo pisania, jeśli użyjesz nazwanych funkcji ... mają one przydatną właściwość name... więc możesz po prostu użyć ExampleCtrl.namezamiast duplikować ... trzykrotnie.
Antti Pihlaja
0

Nie tak wdzięczne, ale bardzo proste w implementacji rozwiązanie - przy użyciu zmiennej globalnej.

W „pierwszym” pliku:


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

w „drugim”, „trzecim” itd.:


myApp.controller('MyController', function($scope) {
    .... 
    }); 
użytkownik3682640
źródło
używam tego kodu, ale nadal nie mogę załadować kontrolera? wyrzuca błąd: Błąd: [ng: areq] Argument „ProductCtrl” nie jest funkcją, został niezdefiniowany.
QViet
7
to jest naprawdę zła praktyka
Brendan,
@Kim Jong Un Zobaczysz ten błąd, jeśli nie dodasz / konkatenujesz kontrolera do utworzonego modułu. Będzie to działać, jeśli użyjesz następującej składni:angular.module('myApp').controller('ProductCtrl', ['$scope', '$http', function($scope, $http){ //Your ProductCtrl code goes here }]);
Devner,
1
@Brendan, samo stwierdzenie, że coś jest złą praktyką, jest lepsze niż nic - ale niewiele. Powiedz nam, dlaczego zła praktyka pomoże innym.
Mawg mówi o przywróceniu Moniki