Как создать отдельные файлы контроллера 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 будущая помощь и запись решений - вот что такое SO, а не бессмысленные вопросы и ответы.
Fresheyeball

2
@RuslanIsmagilov ваш appCtrlглобальный window.appCtrl. Это не очень хорошая практика.
Fresheyeball

1
@Fresheyeball, проблема этого подхода в том, что важен порядок импорта в index.html, в противном случае - ошибка углового выброса.
Deoxyseia

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, но перед любыми контроллерами / службами / и т.д. ... в противном случае angular не сможет инициализировать ваши контроллеры.


где я должен написать свои зависимости. 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вместо дублирования .. утроить его.
Антти Пихлая

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
@ Брендан, просто заявив, что что-то плохое, лучше, чем ничего, но не намного. Скажите нам, почему плохая практика поможет другим.
Mawg говорит восстановить Monica
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.