单页应用程序中带有AngularJS的多个控制器


102

我想知道如何在单个页面应用程序中使用多个控制器。我试图找出答案,但发现的问题与我的非常相似,但是有很多不同的答案可以解决特定的问题,最终您在单个页面应用程序中不使用多个控制器。

那是因为在单个页面上使用多个控制器并不明智吗?还是只是不可能?

假设我已经在主页上有一个踢屁股图像轮播控制器,但是然后我学习了如何使用模态(比如说),为此我还需要一个新的控制器(或者需要控制器的其他任何东西)。那我该怎么办?

我看到了其他问题的一些答案,他们问的几乎和我差不多,而人们回答“ * OMG。为什么还要这么做,只要这样做...”。

最好的方法是什么,或者您怎么做?

编辑

你们中的许多人都回答只是声明两个控制器,然后使用ng-controller对其进行调用。我在下面使用这段代码,然后使用ng-controller调用MainCtrl。

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

如果不使用ng-controller,为什么还要在这里设置控制器?这就是让我困惑的地方。(我想您不能以这种方式添加两个控制器...)


我不认为可以为一个.html文件声明2个控制器?怎么做?when: /home, controller: MainCtrl。只能添加ng-controller来添加它吗?

3
@Mosho,您已完成第1步,第2步,但没有说明如何或为什么。如果就这么简单,请说明如何。这就像说使用AngularJS,完成。您能详细说明/解释吗?还是从六月开始,他们可能没有回复,其他人可以解释吗?
redfox05 2015年

Answers:


96

问题是什么?要使用多个控制器,只需使用多个ngController指令:

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

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

像往常一样,您将需要在应用程序模块中提供控制器。

做到这一点的最基本的方法可能像声明这样的控制器功能一样简单:

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

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

2
这是怎么做到的?我正在使用那个when /home, controller: MainCtrl

8
如果要使用将每个ng-app放在“ ng-controller”旁边的示例中,请尝试仅将一个“ ng-app”移到“ body”标签中(并删除“每格” ng-app“标签)(如果只有第一个控制器有效)。(我从Angular新手时代起就记得这一点。)
ftexperts 2014年

1
ng-controller在多个DOM元素中使用时遇到的唯一问题是,在我有许多项目通过印刷到DOM的情况下ng-repeat。假设每一个都呼叫ng-controller="myController。从我在应用程序中看到的一些控制台日志中,myController使用在DOM中呈现的EACH元素重新初始化,以对其进行调用....也许我在我的特定用法中搞砸了一些东西,或者超出了OP的范围问题,但很好奇是否其他人都经历过
。...– twknab

91

我认为您缺少“单页应用”的含义。

这并不意味着您实际上将拥有一个.html,而是拥有一个主index.html文件和多个NESTED .html文件。那么为什么要使用单页应用程序呢?因为这样您就不会以标准方式加载页面(即完全刷新整个页面的浏览器调用),而只是使用Angular / Ajax加载内容部分。由于看不到页面更改之间的闪烁,因此给人的印象是您没有移出页面。因此,您感觉好像停留在一页上。

现在,我假设您要为“单页”应用程序提供多个内容:(例如,房屋,联系人,投资组合和商店)。您的单页/多内容应用程序(角度方式)将通过以下方式进行组织:

  • index.html:包含页眉<ng-view>和页脚
  • contacts.html:包含联系表单(无页眉,无页脚)
  • portfolio.html:包含投资组合数据(无页眉无页脚)
  • store.html:包含商店,没有页眉,没有页脚。

您已进入索引,单击名为“联系人”的菜单,会发生什么?Angular将代码替换<ng-view>contacts.html代码

您如何实现的?使用时ngRoute,您将获得类似以下内容:

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'   
        });      
});

这将调用正确的html,并将正确的控制器传递给它(请注意:如果使用路由,不要ng-controller在中指定指令contacts.html

然后,当然,您可以在contacts.html页面中声明尽可能多的ng-controller指令。这些将是ContactCtrl(因此从其继承)的子控制器。但是,对于单个路由,routeProvider您可以在中声明一个控制器,该控制器将充当“部分视图的父控制器”。

编辑想象以下template / contacts.html

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

以上routeProvider将注入一个控制器到您的包含div。基本上上述html自动变为:

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

当我说您可以拥有其他控制器时,意味着您可以将控制器插入内部DOM元素,如下所示:

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

我希望这可以澄清一些事情。

一个


所以,如果您<div ng-controller="FancyStuffController">在body标签内声明了一个eg,例如已经有一个控制器被应用了,<body ng-controller="BodyController">它将起作用吗?我收到有关$apply already in progress何时执行此操作的错误,但我认为其与dpd.js有关。我不认为它只是加载了两次,或者不确定如何加载,但是我对控制器的使用可能试图重新加载它。
blamb

1
@BrianThomas当然可以。注意:如果要在视图中注入控制器,请使用$ routeProvider,不要在div标签上编写ng-controller。
阿德拉(Adhara)

9

我目前正在构建一个单页应用程序。到目前为止,这是我相信可以回答您的问题。我有一个基本模板(base.html),其中有一个带ng-view指令的div 。该指令告诉angular在哪里放置新内容。请注意,我本人对angularjs并不陌生,所以我绝不是说这是最好的方法。

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>

实际上,我也在使用ng-view,以便可以在index.html中使用main.html。但是您有/ home和/ about,并且两个控制器分别用于每个控制器。我只有main.html带有ng-view的index.html。我可以为main.html设置两个控制器,就像您所做的一样when /home

看看这个帖子的第一个答案:stackoverflow.com/questions/17354568/…–
奥斯丁

好吧,我知道如何设置更多when的。我想要一个模板有两个控制器。还是老兄,我误会了你想告诉我的内容?

代替使用控制器,请尝试使用指令。您可以在一个模板上使用许多指令。如果您仍然想使用控制器,请观看以下视频,了解指令如何与控制器链接: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可以访问div菜单。和widgetController都可以访问。


这似乎很简单,但没有投票。这是最佳实践,还是不好?
redfox05 2015年

1
如果您有很多页面100+控制器,您将怎么做!
ArifMustafa

3

我们可以简单地在同一模块中声明多个控制器。这是一个例子:

  <!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

我只是对应用程序做了一个简单的声明

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

然后我建立了一个服务和两个控制器

对于每个控制器,我在JS中都有一行

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

在HTML中,我在周围的div中声明了应用范围

<div ng-app="app">

并且每个控制器的作用域分别在自己的周围div(在应用div中)

<div ng-controller="EditableRowCtrl">

这很好


0

您也可以将所有模板视图嵌入到主html文件中。例如:

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

这样,如果每个模板都需要不同的控制器,那么您仍然可以使用角度路由器。请参阅此插件以获取工作示例 http://plnkr.co/edit/9X0fT0Q9MlXtHVVQLhgr?p=preview

这样,一旦应用程序从服务器发送到客户端,它就完全是自包含的,假设它不需要发出任何数据请求,等等。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.