Як створити окремі файли контролера AngularJS?


315

У мене є всі мої контролери AngularJS в одному файлі, controllers.js. Цей файл структурований так:

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

Що я хотів би зробити, це помістити Ctrl1 і Ctrl2 в окремі файли. Потім я б включив обидва файли до свого index.html, але як це слід структурувати? Я спробував зробити щось подібне, і це видає помилку в консолі веб-браузера, кажучи, що вона не може знайти мої контролери. Якісь підказки?

Я шукав StackOverflow і знайшов подібне запитання - однак, цей синтаксис використовує інший фреймворк (CoffeeScript) поверх Angular, і тому я не зміг дотримуватися.


AngularJS: Як створити контролери в декількох файлах

Відповіді:


399

Файл один:

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

Файл другий:

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

}]);

Файл три:

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

}]);

Додайте до цього порядку. Я рекомендую 3 файли, щоб декларація модуля була самостійною.


Що стосується структури папок, то на цю тему існує багато багато думок, але ці дві досить непогані

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

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


1
Якщо ОП вказує на плутанину щодо синтаксису CoffeeScript, можливо, було б краще не використовувати його у своїй відповіді?
Андрій

3
@Andrew imho допомога в майбутньому та створення записів рішень - це те, про що йдеться насправді, а не сучасні питання q і a.
Fresheyeball

2
@RuslanIsmagilov ваш appCtrlє глобальним window.appCtrl. Це не є хорошою практикою.
Fresheyeball

1
@Fresheyeball, проблема такого підходу полягає в тому, який порядок імпорту в index.html важливий, інакше - кутова помилка випромінювання.
Деоксисея

2
@hendryau, добре, я працював з назвою модуля, присутнього в ОП. Однак деякі вважають, що в організаційному плані краще мати декілька модулів, розміщених на імені, а не центральний модуль додатків.
Fresheyeball

177

Використання API angular.module з масивом в кінці підкаже angular створити новий модуль:

myApp.js

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

Використання його без масиву - це фактично функція отримання. Отже, щоб розділити контролери, ви можете:

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

Під час імпорту Javascript просто переконайтеся, що myApp.js після AngularJS, але перед будь-якими контролерами / послугами / тощо ... інакше кутовий не зможе ініціалізувати ваші контролери.


куди мені написати свої залежності. var myapp = angular.module ('demo', ['ngRoute', 'ngCookies', 'ui.bootstrap', 'nvd3ChartDirectives', 'ui-rangeSlider', 'textAngular', 'angularTreeview']);
vipin

@vipin так само, як і те, що ви ввели, але переконайтеся, що це вище будь-яких контролерів, служб тощо. Технічно вам не потрібно оголошувати var myapp = ...; тому що кутовий збереже це для вас.
Джиммі Ау

@JimmyAu Де завантажуються Ctrl1.js та Ctrl2.js, щоб сторінка могла ним користуватися? У мене myApp.js завантажується відразу після кутового, але на сторінці не знайдено контролерів. Чи потрібно я їх явно додавати як сценарій у поданні, яке йому потрібно? Або мені все одно доводиться включати кожен файл контролера на кожну сторінку?
Сінестетик

2
Дякуємо, що пояснили, чому потрібен лише перший дзвінок [].
Джим Б.

49

Хоча обидві відповіді технічно правильні, я хочу ввести інший вибір синтаксису для цієї відповіді. Цей imho полегшує читання того, що відбувається з ін'єкцією, розмежування тощо.

Файл перший

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

Файл другий

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

Файл третій

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

Цікаво, що це заважає мені переходити до декількох файлів, щоб зареєструвати контролер
mrwaim

4
Я бачу багато кодування подібного. Яка перевага? мати $ inject та функцію відокремлену.
Олександр Ісус Гена

2
Я вважаю, що це полегшує читання коду. Я знаю, що саме вводять. Подумайте про це як про «поділ проблем» по черзі.
jason328

2
Цей код не тільки створює більш читабельний код, його набагато простіше налагоджувати, і зменшує кількість вкладеного коду зворотного виклику (див. Github.com/johnpapa/angular-styleguide/blob/master/a1/… )
rfornal

Якби я міг поставити +1 цьому 1000 разів, я б - браво!
Ден Чейз

17

Що з цим рішенням? Модулі та контролери у файлах (в кінці сторінки) Він працює з декількома контролерами, директивами тощо:

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 також має рекомендації щодо найкращих практик щодо кутової структури додатків, які мені дуже подобається групувати за контекстом. Не всі html в одній папці, але, наприклад, всі файли для входу (html, css, app.js, controller.js тощо). Тож якщо я працюю над модулем, всі директиви знайти простіше.


3

Для стислості, ось зразок ES2015, який не покладається на глобальні змінні

// 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
Ви можете заощадити набравши досить, якщо використовували названі функції .. вони мають зручну властивість name.. тож ви можете просто використовувати ExampleCtrl.nameзамість дублювання .. триплікації.
Antti Pihlaja

0

Не настільки витончено, але дуже просто в застосуванні рішення - за допомогою глобальної змінної.

У файлі "перший":


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

у "другому", "третьому" тощо:


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

я використовую цей код, але все ще не можу завантажити свій контролер? це помилка кидка: Помилка: [ng: areq] Аргумент 'ProductCtrl' не є функцією, не визначений.
QViet

7
це дійсно погана практика
Брендан

@Kim Jong Un Ви побачите цю помилку, якщо не додати / зв'язати контролер до створеного вами модуля. Так воно спрацює, якщо використовувати такий синтаксис:angular.module('myApp').controller('ProductCtrl', ['$scope', '$http', function($scope, $http){ //Your ProductCtrl code goes here }]);
Devner

1
@Brendan, просто заявивши, що щось є поганою практикою, краще, ніж нічого - але не набагато. Розкажіть, чому це погана практика допоможе іншим.
Мауг каже, що повернемо Моніку
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.