¿Cómo definir dos aplicaciones / módulos angulares en una página?

118

Estoy tratando de agregar dos aplicaciones / módulos angulares a una página. En los violines a continuación, puede ver que siempre solo el primer módulo, al que se hace referencia en el código html, funcionará correctamente, mientras que el segundo no es reconocido por angular.

En este violín solo podemos ejecutar el doSearch2método, mientras que en este violín solo el doSearchmétodo funciona correctamente.

Estoy buscando la forma de colocar correctamente dos módulos angulares en una página.

Thomas Kremmel
fuente

Respuestas:

123

Solo se puede arrancar automáticamente una aplicación AngularJS por documento HTML. La primera ngApp que se encuentra en el documento se utilizará para definir el elemento raíz para autoarrancar como una aplicación. Para ejecutar múltiples aplicaciones en un documento HTML, debe arrancarlas manualmente usando angular.bootstrap en su lugar. Las aplicaciones de AngularJS no se pueden anidar entre sí. - http://docs.angularjs.org/api/ng.directive:ngApp

Ver también

Mark Rajcok
fuente
@MarkRajcok Entonces, ¿es una buena práctica tener solo un módulo por documento HTML? El ejemplo "Wire up a Backend" en los conjuntos de páginas principales de AngularJS ng-app="project"y dice que "esto le permite tener módulos que se ejecutan en diferentes partes de la página", pero el documento ngApp establece que "solo se puede usar una directiva por documento HTML".
theblang
9
@mattblang, los módulos están asociados con aplicaciones angulares y no con documentos HTML. Normalmente, solo necesita una aplicación por página / documento, pero si desea ejecutar múltiples aplicaciones angulares (cada una de las cuales puede usar uno o más módulos) en la misma página / documento, deberá iniciar manualmente cada una de ellas. - no lo use ng-app(porque no funcionará). ng-appsolo se puede utilizar una vez por documento HTML. En realidad, es solo un atajo si solo tiene una aplicación en la página, que es el caso normal.
Mark Rajcok
1
¿Hay algún ejemplo de esto? Veo la concisa documentación de la API de boostrap pero no puedo hacer que funcione. Lo he buscado en Google por un tiempo y no parece haber un solo ejemplo de trabajo. Además, ¿cómo diablos funcionaría esto con las rutas? Obviamente hay un problema de colisión.
Robert Christian
Además, me gusta mucho la forma en que el uso de ng-app muestra a otro desarrollador exactamente qué parte de la página está siendo controlada por qué módulo. ¿No hay forma de utilizar el marcado en la página para lograr esto? ¿O al menos, alguna pista en el marcado?
chrismarx
1
Los dos primeros párrafos de la directiva ng-app lo dicen todo - docs.angularjs.org/api/ng.directive:ngApp
simo
38

Creé una directiva alternativa que no tiene ngApplimitaciones. Se llama ngModule. Así es como se vería su código cuando lo usa:

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

Es esencialmente el mismo código utilizado internamente por AngularJS sin las limitaciones.

Luis perez
fuente
luisperezphd: Leí la publicación de tu blog. ¿Hay alguna forma de anidar aplicaciones (por ejemplo, un generador de widgets con un widget cargado en AJAX) o detectar si una página ya tiene una aplicación e inyectar otra aplicación como dependencia de la primera? Acabo de publicar mi pregunta aquí con más detalles de exactamente lo que estoy tratando de lograr. ¡Gracias!
Daniel Bonnell
@ACIDSTEALTH El hecho de que AngularJS esté informando que el elemento ya arrancó significa que debe haber alguna forma de saberlo, aunque ese código podría ser interno de AngularJS. Para averiguarlo, puede hacer referencia a la versión no minificada de AngularJS y el punto de interrupción en ese error para ver la condición if. Por lo que puedo ver en el enlace de su pregunta de StackOverflow, parece que desea "inyectar" dinámicamente un módulo en tiempo de ejecución. Si es así, es posible que desee echar un vistazo a este artículo: weblogs.asp.net/dwahlin/…
Luis Perez
Hola @LuisPerez, revisé su sitio web. Lo cansé en mi máquina. angularJS no detecta "ng-modules" / "ng-module". ¿Necesito alguna referencia incluida en mi archivo?
sujay kodamala
Sí @sujaykodamala, ngModule no está integrado en AngularJS, es una directiva que creé. Puedes descargarlo desde GitHub. Puede encontrarlo aquí: github.com/luisperezphd/ngModule
Luis Perez
¡Hola @Luis Perez! Estaba revisando la publicación de tu blog y son realmente increíbles. Si tiene tiempo, ¿podría consultar mi publicación aquí para resolver un problema? Stackoverflow.com/questions/46952478/… . Gracias.
user8512043
19

¿Por qué desea utilizar varias [ng-app]? Dado que Angular se reanuda mediante el uso de módulos, puede usar una aplicación que use múltiples dependencias.

Javascript:

// setter syntax -> initializing other module for demonstration
angular.module('otherModule', []);

angular.module('app', ['otherModule'])
.controller('AppController', function () {
    // ...do something
});

// getter syntax
angular.module('otherModule')
.controller('OtherController', function () {
    // ...do something
});

HTML:

<div ng-app="app">
    <div ng-controller="AppController">...</div>
    <div ng-controller="OtherController">...</div>
</div>

EDITAR

Tenga en cuenta que si desea usar el controlador dentro del controlador, debe usar la sintaxis controllerAs, así:

<div ng-app="app">
    <div ng-controller="AppController as app">
        <div ng-controller="OtherController as other">...</div>
    </div>
</div>
Monje mono
fuente
Error no detectado: [$ injector: moduler] errors.angularjs.org/1.3.14/$injector/…… criptMinification% 2Fbower_components% 2Fangular% 2Fangular.min.js% 3A17% 3A381)
Anandaraja_Srinivasan
¿Has intentado invertir el orden de los 2 módulos? ('OtherModule' antes de 'app') Porque, uso mucho esta solución y funciona perfectamente ...
Monkey Monk
1
Okay ! He visto un error en el ejemplo de Javascript que proporciono. ¡Creo que ya está arreglado! Para que conste, usaré la sintaxis del setter en 2 lugares para el mismo módulo ... ¡lo cual obviamente no está permitido! :-)
Monkey Monk
la forma en que posamos para hacerlo
Harry Bosh
9

Puede arrancar múltiples aplicaciones angulares, pero:

1) Necesita arrancarlos manualmente

2) No debe usar "documento" como raíz, sino el nodo donde está contenida la interfaz angular para:

var todoRootNode = jQuery('[ng-controller=TodoController]');
angular.bootstrap(todoRootNode, ['TodoApp']);

Esto sería seguro.

Wouter
fuente
3

El arranque manual de ambos módulos funcionará. Mira este

  <!-- IN HTML -->
  <div id="dvFirst">
    <div ng-controller="FirstController">
      <p>1: {{ desc }}</p>
    </div>
  </div>

  <div id="dvSecond">
    <div ng-controller="SecondController ">
      <p>2: {{ desc }}</p>
    </div>
  </div>



// IN SCRIPT       
var dvFirst = document.getElementById('dvFirst');
var dvSecond = document.getElementById('dvSecond');

angular.element(document).ready(function() {
   angular.bootstrap(dvFirst, ['firstApp']);
   angular.bootstrap(dvSecond, ['secondApp']);
});

Aquí está el enlace al Plunker http://plnkr.co/edit/1SdZ4QpPfuHtdBjTKJIu?p=preview

NOTA: En html, no hay ng-app. idse ha utilizado en su lugar.

Hari Das
fuente
0

Hice un POC para una aplicación Angular usando múltiples módulos y salidas de enrutador para anidar aplicaciones secundarias en una aplicación de una sola página. Puede obtener el código fuente en: https://github.com/AhmedBahet/ng-sub-apps

Espero que esto ayude

abahet
fuente