Nhiều bộ điều khiển với AngularJS trong ứng dụng trang đơn


102

Tôi muốn biết cách sử dụng nhiều bộ điều khiển cho một ứng dụng trang. Tôi đã cố gắng tìm ra và nhận thấy các câu hỏi rất giống với câu hỏi của tôi, nhưng có rất nhiều câu trả lời khác nhau giải quyết một vấn đề cụ thể mà cuối cùng bạn không sử dụng nhiều bộ điều khiển cho một ứng dụng trang.

Đó có phải là vì sẽ không khôn ngoan nếu sử dụng nhiều bộ điều khiển cho một trang? Hay là nó chỉ là không thể?

Giả sử tôi đã có bộ điều khiển băng chuyền hình ảnh kick-ass hoạt động trên trang chính, nhưng sau đó tôi học cách (giả sử) sử dụng các phương thức và tôi cũng cần một bộ điều khiển mới cho điều đó (hoặc bất kỳ thứ nào khác mà tôi cần một bộ điều khiển). Tôi sẽ làm gì sau đó?

Tôi đã thấy một số câu trả lời cho những câu hỏi khác mà họ hỏi về những điều gần giống như tôi và mọi người trả lời "* OMG. Tại sao bạn thậm chí sẽ làm điều đó, chỉ cần làm điều này ...".

Cách tốt nhất là gì, hoặc làm thế nào để bạn làm điều đó?

Biên tập

Nhiều bạn trả lời chỉ cần khai báo 2 controller rồi dùng ng-controller để gọi nó. Tôi sử dụng đoạn mã này bên dưới và sau đó gọi MainCtrl bằng ng-controller.

app.config(function($routeProvider, $locationProvider) {                        
  $routeProvider                                                                
       .when('/', {                                            
         templateUrl: "templates/main.html",                                               
         controller:'MainCtrl',                                
        })                                                                      
        .otherwise({                      
            template: 'does not exists'   
        });      
});

Tại sao tôi thậm chí cần đặt một bộ điều khiển ở đây nếu tôi chỉ có thể sử dụng ng-controller mà không cần nó? Đây là điều khiến tôi bối rối. (và bạn không thể thêm hai bộ điều khiển theo cách này, tôi nghĩ ...)


Tôi không nghĩ rằng tôi có thể khai báo 2 bộ điều khiển cho một tệp .html? nó được thực hiện như thế nào? when: /home, controller: MainCtrl. không thể thêm bất kỳ hơn thế, hoặc bạn có nghĩa là chỉ gọi nó bằng ng-controller?

3
@Mosho, bạn bước 1, bước 2, đã xong, nhưng không giải thích bằng cách nào hoặc tại sao. Nếu nó đơn giản như vậy, thì hãy giải thích cách làm. Điều đó giống như nói sử dụng AngularJS, Xong. bạn có thể giải thích / giải thích? Hoặc như từ tháng 6, họ có thể không trả lời, người khác có thể giải thích?
redfox05

Câu trả lời:


96

Vấn đề là gì? Để sử dụng nhiều bộ điều khiển, chỉ cần sử dụng nhiều lệnh ngController:

<div class="widget" ng-controller="widgetController">
    <p>Stuff here</p>
</div>

<div class="menu" ng-controller="menuController">
    <p>Other stuff here</p>
</div>

Bạn sẽ cần có bộ điều khiển có sẵn trong mô-đun ứng dụng của mình, như thường lệ.

Cách cơ bản nhất để làm điều đó có thể đơn giản như khai báo các chức năng của bộ điều khiển như sau:

function widgetController($scope) {
   // stuff here
}

function menuController($scope) {
   // stuff here
}

2
Đây có phải là cách điều này được thực hiện? Im sử dụng màwhen /home, controller: MainCtrl

8
Nếu bạn đang tìm ra các ví dụ đặt "ng-app" trong mỗi DIV bên cạnh "ng-controller" của bạn, hãy thử chỉ di chuyển một "ng-app" vào thẻ "body" (và xóa per-div " ng-app ") nếu chỉ bộ điều khiển đầu tiên của bạn hoạt động. (Tôi nhớ điều này từ những ngày mới làm quen với Angular của tôi.)
ftexperts 28/10/14

1
Vấn đề duy nhất mà tôi gặp phải khi sử dụng ng-controllernhiều phần tử DOM, là trong một tình huống mà tôi có NHIỀU mục in vào DOM qua ng-repeat. Giả sử mỗi người trong số này thực hiện một cuộc gọi đến ng-controller="myController. Từ một số nhật ký bảng điều khiển mà tôi đã thấy trong ứng dụng của mình, myControllerkhởi tạo lại với MỖI phần tử được hiển thị trong DOM gọi đến nó .... Có thể tôi đã làm sai điều gì đó trong cách sử dụng cụ thể của mình hoặc có thể vượt quá phạm vi của OP câu hỏi, nhưng tò mò nếu những người khác đã có kinh nghiệm mà ở tất cả hoặc là ....
twknab

91

Tôi nghĩ rằng bạn đang thiếu ý nghĩa "ứng dụng trang đơn".

Điều đó không có nghĩa là bạn sẽ có một tệp .html, thay vào đó bạn sẽ có một index.htmltệp .html chính và một số tệp .html NESTED. Vậy tại sao lại là ứng dụng trang đơn? Bởi vì cách này bạn không tải các trang theo cách chuẩn (tức là lệnh gọi của trình duyệt làm mới hoàn toàn toàn bộ trang) mà bạn chỉ tải phần nội dung bằng Angular / Ajax. Vì bạn không thấy sự chập chờn giữa các lần thay đổi trang, bạn có ấn tượng rằng bạn đã không di chuyển khỏi trang. Vì vậy, bạn cảm thấy như bạn đang ở trên một trang duy nhất.

Bây giờ, tôi giả sử rằng bạn muốn có NHIỀU nội dung cho ứng dụng SINGLE PAGE của mình: (ví dụ: nhà riêng, danh bạ, danh mục đầu tư và cửa hàng. Trang đơn / ứng dụng nhiều nội dung của bạn (theo cách góc cạnh) sẽ được tổ chức theo cách này:

  • index.html: chứa đầu <ng-view>trang và chân trang
  • contacts.html: chứa biểu mẫu liên hệ (không có đầu trang, không có chân trang)
  • portfolio.html: chứa dữ liệu danh mục đầu tư (không có đầu trang không có chân trang)
  • store.html: chứa cửa hàng, không có đầu trang không có chân trang.

Bạn đang ở trong chỉ mục, bạn nhấp vào menu có tên "danh bạ" và điều gì sẽ xảy ra? Angular thay thế <ng-view>thẻ bằng contacts.html

Làm thế nào để bạn đạt được điều đó? với ngRoute, như bạn đang làm, bạn sẽ có một cái gì đó như:

app.config(function($routeProvider, $locationProvider) {                        
  $routeProvider                                                                
       .when('/', {                                            
         templateUrl: "templates/index.html",                                               
         controller:'MainCtrl',                                
        })
        .when('/contacts', {                                            
         templateUrl: "templates/contacts.html",                                               
         controller:'ContactsCtrl',                                
        })                                                                 
        .otherwise({                      
            template: 'does not exists'   
        });      
});

Điều này sẽ gọi html bên phải chuyển bộ điều khiển phù hợp đến nó (xin lưu ý: không chỉ định ng-controllerchỉ thị trong contacts.htmlnếu bạn đang sử dụng các tuyến )

Sau đó, tất nhiên, bạn có thể khai báo bao nhiêu lệnh ng-controller bên trong trang contact.html của mình. Đó sẽ là những bộ điều khiển con của ContactCtrl(do đó kế thừa từ nó). Nhưng đối với một tuyến duy nhất, bên trong routeProvider, bạn có thể khai báo một Bộ điều khiển duy nhất sẽ hoạt động như "Bộ điều khiển cha của chế độ xem từng phần".

CHỈNH SỬA Hãy tưởng tượng các mẫu sau / contact.html

<div>
    <h3>Contacts</h3>
    <p>This is contacts page...</p>
</div>

ở trên routeProvidersẽ đưa một bộ điều khiển vào div chứa của bạn. Về cơ bản, autoaly html ở trên trở thành:

<div ng-controller="ContactsCtrl">
    <h3>Contacts</h3>
    <p>This is contacts page...</p>
</div>

Khi tôi nói rằng bạn có thể có bộ điều khiển khác, có nghĩa là bạn có thể cắm bộ điều khiển vào các phần tử DOM bên trong, như sau:

<div>
    <h3>Contacts</h3>
    <p ng-controller="anotherCtrl">Hello {{name}}! This is contacts page...     
    </p>
</div>

Tôi hy vọng điều này làm sáng tỏ mọi thứ một chút.

A


Vì vậy, nếu bạn khai báo một ví dụ <div ng-controller="FancyStuffController">bên trong một thẻ nội dung đã có một bộ điều khiển được gắn vào nó, ví dụ, <body ng-controller="BodyController">điều này sẽ hoạt động? Tôi nhận được lỗi về $apply already in progressthời điểm tôi làm điều này, nhưng tôi nghĩ rằng nó liên quan đến dpd.js. Không phải vậy, tôi nghĩ nó chỉ tải nó hai lần hoặc cái gì đó, không chắc chắn như thế nào, nhưng cách sử dụng bộ điều khiển của tôi có thể đang cố gắng tải lại nó.
blamb

1
@BrianThomas Chắc chắn, điều đó sẽ hoạt động. Hãy cẩn thận: nếu bạn muốn đưa một bộ điều khiển vào một dạng xem, hãy sử dụng $ routeProvider, không viết ng-controller trên thẻ div.
Adhara

9

Tôi hiện đang trong quá trình xây dựng một ứng dụng trang đơn. Đây là những gì tôi có cho đến nay mà tôi tin rằng sẽ trả lời câu hỏi của bạn. Tôi có một mẫu cơ sở (base.html) có một div với ng-viewchỉ thị trong đó. Lệnh này cho góc biết vị trí để đưa nội dung mới vào. Lưu ý rằng bản thân tôi là người mới làm quen với anglejs nên tôi không có ý nói đây là cách tốt nhất để làm điều đó.

app = angular.module('myApp', []);                                                                             

app.config(function($routeProvider, $locationProvider) {                        
  $routeProvider                                                                
       .when('/home/', {                                            
         templateUrl: "templates/home.html",                                               
         controller:'homeController',                                
        })                                                                      
        .when('/about/', {                                       
            templateUrl: "templates/about.html",     
            controller: 'aboutController',  
        }) 
        .otherwise({                      
            template: 'does not exists'   
        });      
});

app.controller('homeController', [              
    '$scope',                              
    function homeController($scope,) {        
        $scope.message = 'HOME PAGE';                  
    }                                                
]);                                                  

app.controller('aboutController', [                  
    '$scope',                               
    function aboutController($scope) {        
        $scope.about = 'WE LOVE CODE';                       
    }                                                
]); 

base.html

<html>
<body>

    <div id="sideMenu">
        <!-- MENU CONTENT -->
    </div>

    <div id="content" ng-view="">
        <!-- Angular view would show here -->
    </div>

<body>
</html>

thực sự, tôi cũng đang sử dụng ng-view để có thể sử dụng main.html trong index.html của mình. nhưng bạn có / home và / about và hai bộ điều khiển dành cho mỗi cái. Tôi chỉ có index.html với ng-view cho main.html của tôi. Tôi CannetKhách đặt hai bộ điều khiển cho main.html như bạn đã làm vớiwhen /home

Hãy xem câu trả lời đầu tiên từ bài đăng này: stackoverflow.com/questions/17354568/…
Austin

tốt, tôi biết làm thế nào để thiết lập thêm when. Tôi muốn hai bộ điều khiển cho một mẫu duy nhất. Hay là tôi đã hiểu lầm những gì bạn đang cố gắng nói với tôi?

Thay vì sử dụng bộ điều khiển, hãy thử sử dụng các chỉ thị. Bạn có thể sử dụng nhiều chỉ thị trên một mẫu duy nhất. Nếu bạn vẫn muốn sử dụng bộ điều khiển của mình thì đây là video về cách các lệnh có thể liên kết với bộ điều khiển: egghead.io/lessons/angularjs-directives-talking-to-controllers
Austin

6
<div class="widget" ng-controller="widgetController">
    <p>Stuff here</p>
</div>

<div class="menu" ng-controller="menuController">
    <p>Other stuff here</p>
</div>
///////////////// OR ////////////


  <div class="widget" ng-controller="widgetController">
    <p>Stuff here</p>
    <div class="menu" ng-controller="menuController">
        <p>Other stuff here</p>
    </div>
</div>

menuController có quyền truy cập vào div menu. Và widgetController có quyền truy cập vào cả hai.


Điều này có vẻ đơn giản, nhưng không có ủng hộ. Đây là phương pháp tốt nhất, hay xấu?
redfox05

1
bạn sẽ làm gì, nếu bạn có nhiều trang hơn 100 bộ điều khiển! ... thực hành mơ hồ.
ArifMustafa

3

Chúng ta có thể khai báo nhiều hơn một Controller trong cùng một module. Đây là một ví dụ:

  <!DOCTYPE html>
    <html>

    <head>
       <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js">
       </script>
      <title> New Page </title>


    </head> 
    <body ng-app="mainApp"> <!-- if we remove ng-app the add book button [show/hide] will has no effect --> 
      <h2> Books </h2>

    <!-- <input type="checkbox" ng-model="hideShow" ng-init="hideShow = false"></input> -->
    <input type = "button" value = "Add Book"ng-click="hideShow=(hideShow ? false : true)"> </input>
     <div ng-app = "mainApp" ng-controller = "bookController" ng-if="hideShow">
             Enter book name: <input type = "text" ng-model = "book.name"><br>
             Enter book category: <input type = "text" ng-model = "book.category"><br>
             Enter book price: <input type = "text" ng-model = "book.price"><br>
             Enter book author: <input type = "text" ng-model = "book.author"><br>


             You are entering book: {{book.bookDetails()}}
     </div>

    <script>
             var mainApp = angular.module("mainApp", []);

             mainApp.controller('bookController', function($scope) {
                $scope.book = {
                   name: "",
                   category: "",
                   price:"",
                   author: "",


                   bookDetails: function() {
                      var bookObject;
                      bookObject = $scope.book;
                      return "Book name: " + bookObject.name +  '\n' + "Book category: " + bookObject.category + "  \n" + "Book price: " + bookObject.price + "  \n" + "Book Author: " + bookObject.author;
                   }

                };
             });
    </script>

    <h2> Albums </h2>
    <input type = "button" value = "Add Album"ng-click="hideShow2=(hideShow2 ? false : true)"> </input>
     <div ng-app = "mainApp" ng-controller = "albumController" ng-if="hideShow2">
             Enter Album name: <input type = "text" ng-model = "album.name"><br>
             Enter Album category: <input type = "text" ng-model = "album.category"><br>
             Enter Album price: <input type = "text" ng-model = "album.price"><br>
             Enter Album singer: <input type = "text" ng-model = "album.singer"><br>


             You are entering Album: {{album.albumDetails()}}
     </div>

    <script>
             //no need to declare this again ;)
             //var mainApp = angular.module("mainApp", []);

             mainApp.controller('albumController', function($scope) {
                $scope.album = {
                   name: "",
                   category: "",
                   price:"",
                   singer: "",

                   albumDetails: function() {
                      var albumObject;
                      albumObject = $scope.album;
                      return "Album name: " + albumObject.name +  '\n' + "album category: " + albumObject.category + "\n" + "Book price: " + albumObject.price + "\n" + "Album Singer: " + albumObject.singer;
                   }
                };
             });
    </script>

    </body>
    </html>

2

Tôi chỉ đặt một khai báo đơn giản của ứng dụng

var app = angular.module("app", ["xeditable"]);

Sau đó, tôi đã xây dựng một dịch vụ và hai bộ điều khiển

Đối với mỗi bộ điều khiển, tôi có một dòng trong JS

app.controller('EditableRowCtrl', function ($scope, CRUD_OperService) {

Và trong HTML, tôi đã khai báo phạm vi ứng dụng trong một div xung quanh

<div ng-app="app">

và từng phạm vi bộ điều khiển riêng biệt trong div xung quanh của riêng chúng (trong div ứng dụng)

<div ng-controller="EditableRowCtrl">

Điều này hoạt động tốt


0

Bạn cũng có thể nhúng tất cả các dạng xem mẫu vào tệp html chính của mình. Ví dụ:

<body ng-app="testApp">
  <h1>Test App</h1>
  <div ng-view></div>
  <script type = "text/ng-template" id = "index.html">
    <h1>Index Page</h1>
    <p>{{message}}</p>
  </script>
  <script type = "text/ng-template" id = "home.html">
    <h1>Home Page</h1>
    <p>{{message}}</p>
  </script>
</body>

Bằng cách này nếu mỗi mẫu yêu cầu một bộ điều khiển khác nhau thì bạn vẫn có thể sử dụng bộ định tuyến góc. Xem plunk này để biết ví dụ hoạt động http://plnkr.co/edit/9X0fT0Q9MlXtHVVQLhgr?p=preview

Bằng cách này khi ứng dụng được gửi từ máy chủ đến máy khách của bạn, nó hoàn toàn độc lập giả định rằng nó không cần thực hiện bất kỳ yêu cầu dữ liệu nào, v.v.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.