[angularjs] AngularJS Multiple ng-app within a page

I have just started learning Angular JS and created some basic samples however I am stuck with the following problem.

I have created 2 modules and 2 controllers.

shoppingCart -> ShoppingCartController
namesList -> NamesController

There are associated views for each controller. The first View renders fine but second is not rendering. There are no errors.

http://jsfiddle.net/ep2sQ/

Please help me solve this issue.

Also is there any possibility to add console in View to check what values are passed from Controller.

e.g. in the following div can we add console.log and output the controller values

<div ng-app="shoppingCart" ng-controller="ShoppingCartController">
</div>

This question is related to angularjs

The answer is


Here's an example of two applications in one html page and two conrollers in one application :

    <div ng-app = "myapp">
      <div  ng-controller = "C1" id="D1">
         <h2>controller 1 in app 1 <span id="titre">{{s1.title}}</span> !</h2>
      </div>

      <div  ng-controller = "C2" id="D2">
         <h2>controller 2 in app 1 <span id="titre">{{s2.valeur}}</span> !</h2>
      </div>
    </div>
    <script>
        var A1 = angular.module("myapp", [])

        A1.controller("C1", function($scope) {
            $scope.s1 = {};
            $scope.s1.title = "Titre 1";
         });

        A1.controller("C2", function($scope) {
            $scope.s2 = {};
            $scope.s2.valeur = "Valeur 2";
         });
    </script>

    <div ng-app="toapp" ng-controller="C1" id="App2">
        <br>controller 1 in app 2
        <br>First Name: <input type = "text" ng-model = "student.firstName">
        <br>Last Name : <input type="text" ng-model="student.lastName">
        <br>Hello : {{student.fullName()}}
        <br>
    </div>

    <script>
        var A2 = angular.module("toapp", []);
        A2.controller("C1", function($scope) {
            $scope.student={
                firstName:"M",
                lastName:"E",
                fullName:function(){
                    var so=$scope.student;
                    return so.firstName+" "+so.lastName;
                }
            };
        });
        angular.bootstrap(document.getElementById("App2"), ['toapp']);
    </script>
<style>
    #titre{color:red;}
    #D1{ background-color:gray; width:50%; height:20%;}
    #D2{ background-color:yellow; width:50%; height:20%;}
    input{ font-weight: bold; }
</style>


Only one app is automatically initialized. Others have to manually initialized as follows:

Syntax:

angular.bootstrap(element, [modules]);

Example:

_x000D_
_x000D_
<!DOCTYPE html>_x000D_
<html>_x000D_
_x000D_
<head>_x000D_
  <script src="https://code.angularjs.org/1.5.8/angular.js" data-semver="1.5.8" data-require="[email protected]"></script>_x000D_
  <script data-require="[email protected]" data-semver="0.2.18" src="//cdn.rawgit.com/angular-ui/ui-router/0.2.18/release/angular-ui-router.js"></script>_x000D_
  <link rel="stylesheet" href="style.css" />_x000D_
  <script>_x000D_
    var parentApp = angular.module('parentApp', [])_x000D_
  .controller('MainParentCtrl', function($scope) {_x000D_
    $scope.name = 'universe';_x000D_
  });_x000D_
_x000D_
_x000D_
_x000D_
var childApp = angular.module('childApp', ['parentApp'])_x000D_
  .controller('MainChildCtrl', function($scope) {_x000D_
    $scope.name = 'world';_x000D_
  });_x000D_
_x000D_
_x000D_
angular.element(document).ready(function() {_x000D_
  angular.bootstrap(document.getElementById('childApp'), ['childApp']);_x000D_
});_x000D_
    _x000D_
  </script>_x000D_
</head>_x000D_
_x000D_
<body>_x000D_
  <div id="childApp">_x000D_
    <div ng-controller="MainParentCtrl">_x000D_
      Hello {{name}} !_x000D_
      <div>_x000D_
        <div ng-controller="MainChildCtrl">_x000D_
          Hello {{name}} !_x000D_
        </div>_x000D_
      </div>_x000D_
    </div>_x000D_
  </div>_x000D_
</body>_x000D_
_x000D_
</html>
_x000D_
_x000D_
_x000D_

AngularJS API


_x000D_
_x000D_
         var shoppingCartModule = angular.module("shoppingCart", [])_x000D_
          shoppingCartModule.controller("ShoppingCartController",_x000D_
           function($scope) {_x000D_
             $scope.items = [{_x000D_
               product_name: "Product 1",_x000D_
               price: 50_x000D_
             }, {_x000D_
               product_name: "Product 2",_x000D_
               price: 20_x000D_
             }, {_x000D_
               product_name: "Product 3",_x000D_
               price: 180_x000D_
             }];_x000D_
             $scope.remove = function(index) {_x000D_
               $scope.items.splice(index, 1);_x000D_
             }_x000D_
           }_x000D_
         );_x000D_
         var namesModule = angular.module("namesList", [])_x000D_
          namesModule.controller("NamesController",_x000D_
           function($scope) {_x000D_
             $scope.names = [{_x000D_
               username: "Nitin"_x000D_
             }, {_x000D_
               username: "Mukesh"_x000D_
             }];_x000D_
           }_x000D_
         );_x000D_
_x000D_
_x000D_
         var namesModule = angular.module("namesList2", [])_x000D_
          namesModule.controller("NamesController",_x000D_
           function($scope) {_x000D_
             $scope.names = [{_x000D_
               username: "Nitin"_x000D_
             }, {_x000D_
               username: "Mukesh"_x000D_
             }];_x000D_
           }_x000D_
         );_x000D_
_x000D_
_x000D_
         angular.element(document).ready(function() {_x000D_
           angular.bootstrap(document.getElementById("App2"), ['namesList']);_x000D_
           angular.bootstrap(document.getElementById("App3"), ['namesList2']);_x000D_
         });
_x000D_
<!DOCTYPE html>_x000D_
<html>_x000D_
_x000D_
<head>_x000D_
  <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>_x000D_
_x000D_
</head>_x000D_
_x000D_
<body>_x000D_
_x000D_
  <div id="App1" ng-app="shoppingCart" ng-controller="ShoppingCartController">_x000D_
    <h1>Your order</h1>_x000D_
    <div ng-repeat="item in items">_x000D_
      <span>{{item.product_name}}</span>_x000D_
      <span>{{item.price | currency}}</span>_x000D_
      <button ng-click="remove($index);">Remove</button>_x000D_
    </div>_x000D_
  </div>_x000D_
_x000D_
  <div id="App2" ng-app="namesList" ng-controller="NamesController">_x000D_
    <h1>List of Names</h1>_x000D_
    <div ng-repeat="_name in names">_x000D_
      <p>{{_name.username}}</p>_x000D_
    </div>_x000D_
  </div>_x000D_
  <div id="App3" ng-app="namesList2" ng-controller="NamesController">_x000D_
    <h1>List of Names</h1>_x000D_
    <div ng-repeat="_name in names">_x000D_
      <p>{{_name.username}}</p>_x000D_
    </div>_x000D_
  </div>_x000D_
_x000D_
_x000D_
</body>_x000D_
_x000D_
</html>
_x000D_
_x000D_
_x000D_


To run multiple applications in an HTML document you must manually bootstrap them using angular.bootstrap()

HTML

<!-- Automatic Initialization -->
<div ng-app="myFirstModule">
    ...
</div>
<!-- Need To Manually Bootstrap All Other Modules -->
<div id="module2">
    ...
</div>

JS

angular.
  bootstrap(document.getElementById("module2"), ['mySecondModule']);

The reason for this is that only one AngularJS application can be automatically bootstrapped per HTML document. The first ng-app found in the document will be used to define the root element to auto-bootstrap as an application.

In other words, while it is technically possible to have several applications per page, only one ng-app directive will be automatically instantiated and initialized by the Angular framework.


<html>
<head>
    <script src="angular.min.js"></script>
</head>
<body>
<div ng-app="shoppingCartParentModule" >
     <div ng-controller="ShoppingCartController">
        <h1>Your order</h1>
        <div ng-repeat="item in items">
            <span>{{item.product_name}}</span>
            <span>{{item.price | currency}}</span>
            <button ng-click="remove($index);">Remove</button>
        </div>
    </div>

    <div ng-controller="NamesController">
        <h1>List of Names</h1>
        <div ng-repeat="name in names">
            <p>{{name.username}}</p>
        </div>
    </div>
</div>
</body>
<script>
var shoppingCartModule = angular.module("shoppingCart", [])
            shoppingCartModule.controller("ShoppingCartController",
                function($scope) {
                    $scope.items = [
                        {product_name: "Product 1", price: 50},
                        {product_name: "Product 2", price: 20},
                        {product_name: "Product 3", price: 180}
                    ];
                    $scope.remove = function(index) {
                        $scope.items.splice(index, 1);
                    }
                }
            );
            var namesModule = angular.module("namesList", [])
            namesModule.controller("NamesController",
                function($scope) {
                    $scope.names = [
                        {username: "Nitin"},
                        {username: "Mukesh"}
                    ];
                }
            );
   angular.module("shoppingCartParentModule",["shoppingCart","namesList"])
</script>
</html>

You can merge multiple modules in one rootModule , and assign that module as ng-app to a superior element ex: body tag.

code ex:

    <!DOCTYPE html>
<html>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script src="namesController.js"></script>
<script src="myController.js"></script>
<script>var rootApp = angular.module('rootApp', ['myApp1','myApp2'])</script>
<body ng-app="rootApp">

<div ng-app="myApp1" ng-controller="myCtrl" >
First Name: <input type="text" ng-model="firstName"><br>
Last Name: <input type="text" ng-model="lastName"><br>
<br>
Full Name: {{firstName + " " + lastName}}
</div>

<div ng-app="myApp2" ng-controller="namesCtrl">
<ul>
  <li ng-bind="first">{{first}}
  </li>
</ul>
</div>

</body>
</html>

You can use angular.bootstrap() directly... the problem is you lose the benefits of directives.

First you need to get a reference to the HTML element in order to bootstrap it, which means your code is now coupled to your HTML.

Secondly the association between the two is not as apparent. With ngApp you can clearly see what HTML is associated with what module and you know where to look for that information. But angular.bootstrap() could be invoked from anywhere in your code.

If you are going to do it at all the best way would be by using a directive. Which is what I did. It's called ngModule. Here is what your code would look like using it:

<!DOCTYPE html>
<html>
    <head>
        <script src="angular.js"></script>
        <script src="angular.ng-modules.js"></script>
        <script>
          var moduleA = angular.module("MyModuleA", []);
          moduleA.controller("MyControllerA", function($scope) {
              $scope.name = "Bob A";
          });

          var moduleB = angular.module("MyModuleB", []);
          moduleB.controller("MyControllerB", function($scope) {
              $scope.name = "Steve B";
          });
        </script>
    </head>
    <body>
        <div ng-modules="MyModuleA, MyModuleB">
            <h1>Module A, B</h1>
            <div ng-controller="MyControllerA">
                {{name}}
            </div>
            <div ng-controller="MyControllerB">
                {{name}}
            </div>
        </div>

        <div ng-module="MyModuleB">
            <h1>Just Module B</h1>
            <div ng-controller="MyControllerB">
                {{name}}
            </div>
        </div>
    </body>
</html>

You can get the source code for it at:

http://www.simplygoodcode.com/2014/04/angularjs-getting-around-ngapp-limitations-with-ngmodule/

It's implemented in the same way as ngApp. It simply calls angular.bootstrap() behind the scenes.


_x000D_
_x000D_
// root-app_x000D_
const rootApp = angular.module('root-app', ['app1', 'app2E']);_x000D_
_x000D_
// app1_x000D_
const app11aa = angular.module('app1', []);_x000D_
app11aa.controller('main', function($scope) {_x000D_
  $scope.msg = 'App 1';_x000D_
});_x000D_
_x000D_
// app2_x000D_
const app2 = angular.module('app2E', []);_x000D_
app2.controller('mainB', function($scope) {_x000D_
  $scope.msg = 'App 2';_x000D_
});_x000D_
_x000D_
// bootstrap_x000D_
angular.bootstrap(document.querySelector('#app1a'), ['app1']);_x000D_
angular.bootstrap(document.querySelector('#app2b'), ['app2E']);
_x000D_
<!-- [email protected] -->_x000D_
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.0/angular.min.js"></script>_x000D_
_x000D_
<!-- root-app -->_x000D_
<div ng-app="root-app">_x000D_
_x000D_
  <!-- app1 -->_x000D_
  <div id="app1a">_x000D_
    <div ng-controller="main">_x000D_
      {{msg}}_x000D_
    </div>_x000D_
  </div>_x000D_
_x000D_
  <!-- app2 -->_x000D_
  <div id="app2b">_x000D_
    <div ng-controller="mainB">_x000D_
      {{msg}}_x000D_
    </div>_x000D_
  </div>_x000D_
_x000D_
</div>
_x000D_
_x000D_
_x000D_


You can define a Root ng-App and in this ng-App you can define multiple nd-Controler. Like this

    <!DOCTYPE html>
    <html>
    <script src = "https://ajax.googleapis.com/ajax/libs/angularjs/1.3.3/angular.min.js"></script>

<style>
         table, th , td {
            border: 1px solid grey;
            border-collapse: collapse;
            padding: 5px;
         }

         table tr:nth-child(odd) {
            background-color: #f2f2f2;
         }

         table tr:nth-child(even) {
            background-color: #ffffff;
         }
      </style>

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

      mainApp.controller('studentController1', function ($scope) {
      $scope.student = {
      firstName: "MUKESH",
      lastName: "Paswan",

      fullName: function () {
         var studentObject;
         studentObject = $scope.student;
         return studentObject.firstName + " " + studentObject.lastName;
                     }
                 };
             });

             mainApp.controller('studentController2', function ($scope) {
                 $scope.student = {
                     firstName: "Mahesh",
                     lastName: "Parashar",
                     fees: 500,

                     subjects: [
                        { name: 'Physics', marks: 70 },
                        { name: 'Chemistry', marks: 80 },
                        { name: 'Math', marks: 65 },
                        { name: 'English', marks: 75 },
                        { name: 'Hindi', marks: 67 }
                     ],

                     fullName: function () {
                         var studentObject;
                         studentObject = $scope.student;
                         return studentObject.firstName + " " + studentObject.lastName;
                     }
                 };
             });
          </script>

    <body>
    <div ng-app = "mainApp">
    <div id="dv1"  ng-controller = "studentController1">
    Enter first name: <input type = "text" ng-model = "student.firstName"><br/><br/> Enter last name: <input type = "text" ng-model = "student.lastName"><br/>
    <br/>
     You are entering: {{student.fullName()}}
    </div>

    <div id="dv2" ng-controller = "studentController2">
     <table border = "0">
                <tr>
                   <td>Enter first name:</td>
                   <td><input type = "text" ng-model = "student.firstName"></td>
                </tr>

                <tr>
                   <td>Enter last name: </td>
                   <td>
                      <input type = "text" ng-model = "student.lastName">
                   </td>
                </tr>

                <tr>
                   <td>Name: </td>
                   <td>{{student.fullName()}}</td>
                </tr>

                <tr>
                   <td>Subject:</td>

                   <td>
                      <table>
                         <tr>
                            <th>Name</th>.
                            <th>Marks</th>
                         </tr>

                         <tr ng-repeat = "subject in student.subjects">
                            <td>{{ subject.name }}</td>
                            <td>{{ subject.marks }}</td>
                         </tr>

                      </table>
                   </td>

                </tr>
             </table>

          </div>
    </div>

    </body>
    </html>

I have modified your jsfiddle, can make top most module as rootModule for rest of the modules. Below Modifications updated on your jsfiddle.

  1. Second Module can injected in RootModule.
  2. In Html second defined ng-app placed inside the Root ng-app.

Updated JsFiddle: http://jsfiddle.net/ep2sQ/1011/


In my case I had to wrap the bootstrapping of my second app in angular.element(document).ready for it to work:

angular.element(document).ready(function() {
  angular.bootstrap(document.getElementById("app2"), ["app2"]);
});   

Use angular.bootstrap(element, [modules], [config]) to manually start up AngularJS application (for more information, see the Bootstrap guide).

See the following example:

_x000D_
_x000D_
// root-app_x000D_
const rootApp = angular.module('root-app', ['app1', 'app2']);_x000D_
_x000D_
// app1_x000D_
const app1 = angular.module('app1', []);_x000D_
app1.controller('main', function($scope) {_x000D_
  $scope.msg = 'App 1';_x000D_
});_x000D_
_x000D_
// app2_x000D_
const app2 = angular.module('app2', []);_x000D_
app2.controller('main', function($scope) {_x000D_
  $scope.msg = 'App 2';_x000D_
});_x000D_
_x000D_
// bootstrap_x000D_
angular.bootstrap(document.querySelector('#app1'), ['app1']);_x000D_
angular.bootstrap(document.querySelector('#app2'), ['app2']);
_x000D_
<!-- [email protected] -->_x000D_
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.0/angular.min.js"></script>_x000D_
_x000D_
<!-- root-app -->_x000D_
<div ng-app="root-app">_x000D_
_x000D_
  <!-- app1 -->_x000D_
  <div id="app1">_x000D_
    <div ng-controller="main">_x000D_
      {{msg}}_x000D_
    </div>_x000D_
  </div>_x000D_
_x000D_
  <!-- app2 -->_x000D_
  <div id="app2">_x000D_
    <div ng-controller="main">_x000D_
      {{msg}}_x000D_
    </div>_x000D_
  </div>_x000D_
_x000D_
</div>
_x000D_
_x000D_
_x000D_