AngularJS Multiple ng-app dentro de una página

180

Acabo de comenzar a aprender Angular JS y creé algunas muestras básicas, sin embargo, estoy atascado con el siguiente problema.

He creado 2 módulos y 2 controladores.

shoppingCart -> ShoppingCartController
namesList -> NamesController

Hay vistas asociadas para cada controlador. La primera vista se muestra bien, pero la segunda no. No hay errores

http://jsfiddle.net/ep2sQ/

Por favor ayudame a resolver este problema.

También existe la posibilidad de agregar una consola en la Vista para verificar qué valores se pasan del Controlador.

por ejemplo, en el siguiente div podemos agregar console.log y generar los valores del controlador

<div ng-app="shoppingCart" ng-controller="ShoppingCartController">
</div>
Nitin Mukesh
fuente
10
puede ser esto ayudará: stackoverflow.com/questions/12860595/…
Cherniv
Gracias Cherniv Esto es muy útil y resolví el problema usando el enlace que proporcionaste. ¿Podría también proporcionar información sobre cómo usar console.log para volcar el Controlador dentro de Ver / Plantilla {{console.log}} no funciona.
Nitin Mukesh
de nada. tenga en cuenta que ya está haciendo "consola" en una vista, esto: en {{item.product_name}}realidad "imprime" un valor de su modelo
Cherniv
1
¿Hay algo malo en crear múltiples aplicaciones para una aplicación web? Tengo este proyecto donde cada página html tiene su propia aplicación, quiero saber si el rendimiento se verá afectado de todos modos.
T. Rex
Si bien es posible iniciar más de una aplicación AngularJS por página, no probamos activamente en este escenario. Es posible que tenga problemas, especialmente con aplicaciones complejas, por lo que se recomienda precaución. Consulte la Guía del desarrollador de AngularJS: Bootstrap .
georgeawg

Respuestas:

190

Básicamente, como mencionó Cherniv, necesitamos arrancar los módulos para tener múltiples aplicaciones ng dentro de la misma página. Muchas gracias por todas las entradas.

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.bootstrap(document.getElementById("App2"), ['namesList']);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular.min.js"></script>

<div id="App1" ng-app="shoppingCart" 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 id="App2" ng-app="namesList" ng-controller="NamesController">
  <h1>List of Names</h1>
  <div ng-repeat="_name in names">
    <p>{{_name.username}}</p>
  </div>
</div>

Nitin Mukesh
fuente
2
Puede crear una directiva para hacer esto en su lugar stackoverflow.com/a/22898036/984780
Luis Perez
33
La documentación angular dice que al iniciar manualmente una aplicación, NO para usar la directiva ngApp. Entonces ng-app = "namesList" (podría / debería) ser eliminado. docs.angularjs.org/guide/bootstrap
Mike_K
44
Para aquellos que tienen ng-app en dos archivos js separados, el siguiente código podría ayudar a angular.element (document) .ready (function () {angular.bootstrap (document.getElementById ("App2"), ['namesList']) ;});
Siva Kannan
3
Nota: en mi aplicación, tuve que poner esta línea "angular.bootstrap (document.getElementById (" App2 "), ['namesList']);" in $ (document) .ready function
La masse
No funciona para mí. Solo la primera aplicación ng funciona correctamente
SIVAKUMAR.J
120

Para ejecutar varias aplicaciones en un documento HTML, debe iniciarlas manualmente utilizando 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']);

La razón de esto es que solo una aplicación AngularJS se puede iniciar automáticamente por documento HTML. Lo primero que se ng-appencuentre en el documento se usará para definir el elemento raíz para auto-bootstrap como una aplicación.

En otras palabras, si bien es técnicamente posible tener varias aplicaciones por página, el marco angular solo instanciará e inicializará automáticamente una directiva ng-app.

AlwaysALearner
fuente
20
Solo se ngApppuede cargar automáticamente una directiva por documento HTML, pero puede tener varias aplicaciones siempre que inicie manualmente las siguientes.
JaredMcAteer
@CodeHater, ¿dónde está namesListubicado el módulo? ¿Podría por favor actualizar su respuesta, para que sea más clara?
Eugene
Esto está mal. PUEDES tener múltiples ng-app. Ver stackoverflow.com/a/24867989/753632
AndroidDev
3
@AndroidDev, no te sigo. El enlace al que hace referencia no muestra múltiples atributos de ng-app.
Jpnh
42

Puede usar angular.bootstrap()directamente ... el problema es que pierde los beneficios de las directivas.

Primero debe obtener una referencia al elemento HTML para arrancarlo, lo que significa que su código ahora está acoplado a su HTML.

En segundo lugar, la asociación entre los dos no es tan evidente. Con ngAppusted puede ver claramente qué HTML está asociado con qué módulo y sabe dónde buscar esa información. Pero angular.bootstrap()podría invocarse desde cualquier parte de su código.

Si va a hacerlo de la mejor manera, sería usando una directiva. Que es lo que hice. Se llama ngModule. Así es como se vería su código al usarlo:

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

Puede obtener el código fuente en:

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

Se implementa de la misma manera que ngApp. Simplemente llama angular.bootstrap()detrás de escena.

Luis perez
fuente
9

En mi caso, tuve que completar el arranque de mi segunda aplicación angular.element(document).readypara que funcione:

angular.element(document).ready(function() {
  angular.bootstrap(document.getElementById("app2"), ["app2"]);
});   
Saeb Amini
fuente
V1.6 en desuso: uso en angular.element(callback)lugar de angular.element(document).ready(callback)). Ver AngularJS angular.element API Reference . También github.com/angular/angular.js/commit/…
georgeawg
7

Aquí hay un ejemplo de dos aplicaciones en una página html y dos conrollers en una aplicación:

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

merrais
fuente
6

Puede fusionar múltiples módulos en un rootModule y asignar ese módulo como ng-app a un elemento superior, por ejemplo: etiqueta de cuerpo.

código 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>
Vijay Tripathi
fuente
44
Está anidando dos aplicaciones diferentes dentro de la aplicación root, Angular no permite anidar aplicaciones
codin
4

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


         var namesModule = angular.module("namesList2", [])
          namesModule.controller("NamesController",
           function($scope) {
             $scope.names = [{
               username: "Nitin"
             }, {
               username: "Mukesh"
             }];
           }
         );


         angular.element(document).ready(function() {
           angular.bootstrap(document.getElementById("App2"), ['namesList']);
           angular.bootstrap(document.getElementById("App3"), ['namesList2']);
         });
<!DOCTYPE html>
<html>

<head>
  <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>

</head>

<body>

  <div id="App1" ng-app="shoppingCart" 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 id="App2" ng-app="namesList" ng-controller="NamesController">
    <h1>List of Names</h1>
    <div ng-repeat="_name in names">
      <p>{{_name.username}}</p>
    </div>
  </div>
  <div id="App3" ng-app="namesList2" ng-controller="NamesController">
    <h1>List of Names</h1>
    <div ng-repeat="_name in names">
      <p>{{_name.username}}</p>
    </div>
  </div>


</body>

</html>

Praneeth
fuente
Solo una extensión para tener múltiples ng-app en una sola página Tuve que combinar el código saeb-amini y @Nithin Mukesh - Gracias a ambos
Praneeth
Este concepto me está funcionando. angular.element (document) .ready (function () {angular.bootstrap (document.getElementById ("App2"), ['namesList']); angular.bootstrap (document.getElementById ("App3"), ['namesList2' ]);});
SIVAKUMAR.J
2

Solo una aplicación se inicializa automáticamente. Otros deben inicializarse manualmente de la siguiente manera:

Sintaxis:

angular.bootstrap(element, [modules]);

Ejemplo:

<!DOCTYPE html>
<html>

<head>
  <script src="https://code.angularjs.org/1.5.8/angular.js" data-semver="1.5.8" data-require="[email protected]"></script>
  <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>
  <link rel="stylesheet" href="style.css" />
  <script>
    var parentApp = angular.module('parentApp', [])
  .controller('MainParentCtrl', function($scope) {
    $scope.name = 'universe';
  });



var childApp = angular.module('childApp', ['parentApp'])
  .controller('MainChildCtrl', function($scope) {
    $scope.name = 'world';
  });


angular.element(document).ready(function() {
  angular.bootstrap(document.getElementById('childApp'), ['childApp']);
});
    
  </script>
</head>

<body>
  <div id="childApp">
    <div ng-controller="MainParentCtrl">
      Hello {{name}} !
      <div>
        <div ng-controller="MainChildCtrl">
          Hello {{name}} !
        </div>
      </div>
    </div>
  </div>
</body>

</html>

API AngularJS

Premraj
fuente
1

Puede definir una aplicación ng raíz y en esta aplicación ng puede definir múltiples nd-Controler. Me gusta esto

    <!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>
santosh
fuente
1

// root-app
const rootApp = angular.module('root-app', ['app1', 'app2E']);

// app1
const app11aa = angular.module('app1', []);
app11aa.controller('main', function($scope) {
  $scope.msg = 'App 1';
});

// app2
const app2 = angular.module('app2E', []);
app2.controller('mainB', function($scope) {
  $scope.msg = 'App 2';
});

// bootstrap
angular.bootstrap(document.querySelector('#app1a'), ['app1']);
angular.bootstrap(document.querySelector('#app2b'), ['app2E']);
<!-- [email protected] -->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.0/angular.min.js"></script>

<!-- root-app -->
<div ng-app="root-app">

  <!-- app1 -->
  <div id="app1a">
    <div ng-controller="main">
      {{msg}}
    </div>
  </div>

  <!-- app2 -->
  <div id="app2b">
    <div ng-controller="mainB">
      {{msg}}
    </div>
  </div>

</div>

Ruben Rivero
fuente
0

He modificado su jsfiddle, puedo hacer que el módulo más superior sea rootModule para el resto de los módulos. A continuación las modificaciones actualizadas en su jsfiddle.

  1. El segundo módulo puede inyectarse en RootModule.
  2. En HTML, la segunda aplicación ng definida se coloca dentro de la aplicación ng raíz.

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

Mano
fuente
¿Alguna idea de por qué esto solo evalúa el primero ng-app? jsfiddle.net/vwcbtzdg
Si8
Primero solo se inicializa automáticamente, otros deben inicializarse manualmente
Mano
0

Úselo angular.bootstrap(element, [modules], [config])para iniciar manualmente la aplicación AngularJS (para obtener más información, consulte la guía Bootstrap ).

Vea el siguiente ejemplo:

// root-app
const rootApp = angular.module('root-app', ['app1', 'app2']);

// app1
const app1 = angular.module('app1', []);
app1.controller('main', function($scope) {
  $scope.msg = 'App 1';
});

// app2
const app2 = angular.module('app2', []);
app2.controller('main', function($scope) {
  $scope.msg = 'App 2';
});

// bootstrap
angular.bootstrap(document.querySelector('#app1'), ['app1']);
angular.bootstrap(document.querySelector('#app2'), ['app2']);
<!-- [email protected] -->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.0/angular.min.js"></script>

<!-- root-app -->
<div ng-app="root-app">

  <!-- app1 -->
  <div id="app1">
    <div ng-controller="main">
      {{msg}}
    </div>
  </div>

  <!-- app2 -->
  <div id="app2">
    <div ng-controller="main">
      {{msg}}
    </div>
  </div>

</div>

Yas
fuente
-5
<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>
Sirigiri Chandu
fuente
1
Agregue descripción a su respuesta lo que ha publicado
Abhinav Singh Maurya
1
¡Necesita comentarios que expliquen qué está pasando! ¡Buen intento!
Eric Brown - Cal