วิธีสร้างไฟล์คอนโทรลเลอร์ 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
หาก OP ระบุความสับสนเกี่ยวกับไวยากรณ์ของ CoffeeScript อาจจะเป็นการดีที่สุดถ้าไม่ใช้ในคำตอบของคุณ
Andrew

3
@Andrew imho ความช่วยเหลือในอนาคตและการทำบันทึกการแก้ปัญหาคือสิ่งที่เป็นดังนั้นจริงๆเกี่ยวกับไม่ได้มาก่อนคิวและ
Fresheyeball

2
@RuslanIsmagilov ของคุณเป็นโลกappCtrl window.appCtrlนั่นไม่ใช่วิธีปฏิบัติที่ดี
Fresheyeball

1
@Fresheyeball ปัญหาของวิธีการนี้คือลำดับการนำเข้าใน index.html เป็นสิ่งสำคัญมิฉะนั้นจะเกิดข้อผิดพลาดในเชิงมุม
Deoxyseia

2
@ hendryau ดีฉันทำงานกับชื่อโมดูลปัจจุบันใน OP ที่กล่าวว่าบางคนรู้สึกว่ามันเป็นองค์กรที่ดีกว่าที่จะมีโมดูลระยะห่างหลายชื่อมากกว่าโมดูลแอปกลาง
Fresheyeball

177

การใช้ angular.module API กับอาเรย์ที่ส่วนท้ายจะบอกให้แองกูลาร์สร้างโมดูลใหม่:

myApp.js

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

การใช้มันโดยไม่ต้องใช้อาเรย์เป็นฟังก์ชั่นของ getter เพื่อแยกตัวควบคุมของคุณคุณสามารถทำ:

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

ในระหว่างการนำเข้าจาวาสคริปต์ให้แน่ใจว่าmyApp.jsอยู่หลัง AngularJS แต่ก่อนตัวควบคุม / บริการ / อื่น ๆ ... มิฉะนั้นเชิงมุมจะไม่สามารถเริ่มต้นตัวควบคุมของคุณได้


ฉันควรเขียนการอ้างอิงของฉันที่ไหน var myapp = angular.module ('สาธิต', ['ngRoute', 'ngCookies', 'ui.bootstrap', 'nvd3ChartDirectives', 'ui-rangeSlider', 'textAngular', 'angularTreeview'])
vipin

@ vipin เหมือนกับสิ่งที่คุณพิมพ์ แต่ให้แน่ใจว่าอยู่เหนือตัวควบคุมบริการและอื่น ๆ ในทางเทคนิคคุณไม่จำเป็นต้องประกาศ var myapp = ... ; เพราะเชิงมุมจะเก็บไว้ให้คุณ
Jimmy Au

@JimmyAu โหลด Ctrl1.js และ Ctrl2.js ที่ไหนเพื่อให้หน้าสามารถใช้งานได้ ฉันโหลด myApp.js หลังแองกูลาร์แล้ว แต่หน้าไม่พบคอนโทรลเลอร์ ฉันต้องเพิ่มอย่างชัดเจนเป็นสคริปต์ในมุมมองที่ต้องการหรือไม่ หรือฉันยังต้องรวมไฟล์คอนโทรลเลอร์ทุกไฟล์ไว้ในทุกหน้า?
Sinaesthetic

2
ขอบคุณที่ให้ความกระจ่างว่าเพราะเหตุใดการโทรครั้งแรกจึงจำเป็น
Jim B.

49

แม้ว่าคำตอบทั้งสองจะถูกต้องทางเทคนิค แต่ฉันต้องการแนะนำทางเลือกไวยากรณ์ที่แตกต่างสำหรับคำตอบนี้ imho นี้ทำให้ง่ายต่อการอ่านสิ่งที่เกิดขึ้นกับการฉีดความแตกต่างระหว่าง ฯลฯ

ไฟล์หนึ่ง

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

ไฟล์ Two

// 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
ฉันเห็นการเข้ารหัสจำนวนมากเช่นนี้ ข้อดีคืออะไร ของการมี $ ฉีดและแยกฟังก์ชั่น
Alaksandar Jesus Gene

2
ฉันเชื่อว่ามันทำให้อ่านง่ายขึ้น ฉันรู้ว่าสิ่งที่ถูกฉีด คิดว่ามันเป็น "การแยกของความกังวล" ในแต่ละบรรทัด
jason328

2
รหัสเช่นนี้ไม่เพียง แต่จะสร้างรหัสที่อ่านได้มากขึ้นง่ายต่อการตรวจแก้จุดบกพร่องและลดจำนวนของรหัสโทรกลับซ้อน (ดูgithub.com/johnpapa/angular-styleguide/blob/master/a1/ … )
rfornal

ถ้าฉันสามารถ +1 สิ่งนี้ 1,000 ครั้งฉันจะ - ไชโย!
Dan Chase

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แทนการพิมพ์ซ้ำ .. triplicating
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 }]);
4994 Devner

1
@Bendan เพียงแค่ระบุว่าบางสิ่งบางอย่างเป็นการปฏิบัติที่ไม่ดีจะดีกว่าไม่มีอะไร - แต่ไม่มาก บอกให้เราทราบว่าทำไมการปฏิบัติที่ไม่ดีจะช่วยผู้อื่น
Mawg กล่าวว่าคืนสถานะโมนิก้า
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.