Comment définir deux applications / modules angulaires sur une seule page?

118

J'essaye d'ajouter deux applications / modules angulaires à une page. Dans les violons ci-dessous, vous pouvez voir que toujours seul le premier module, référencé dans le code html, fonctionnera correctement, alors que le second n'est pas reconnu par angular.

Dans ce violon, nous ne pouvons exécuter que la doSearch2méthode, alors que dans ce violon seule la doSearchméthode fonctionne correctement.

Je cherche comment placer correctement deux modules angulaires sur une seule page.

Thomas Kremmel
la source

Réponses:

123

Une seule application AngularJS peut être amorcée automatiquement par document HTML. Le premier ngApp trouvé dans le document sera utilisé pour définir l'élément racine à amorcer automatiquement en tant qu'application. Pour exécuter plusieurs applications dans un document HTML, vous devez les amorcer manuellement en utilisant angular.bootstrap à la place. Les applications AngularJS ne peuvent pas être imbriquées les unes dans les autres. - http://docs.angularjs.org/api/ng.directive:ngApp

Voir également

Mark Rajcok
la source
@MarkRajcok Alors, est-ce une bonne pratique de n'avoir qu'un seul module par document HTML? L'exemple "Wire up a Backend" sur les principaux ensembles de pages AngularJS ng-app="project"et indique que "cela vous permet d'avoir des modules qui s'exécutent dans différentes parties de la page" mais le document ngApp indique que "une seule directive peut être utilisée par document HTML".
theblang
9
@mattblang, les modules sont associés à des applications Angular, et pas vraiment à des documents HTML. Normalement, vous n'avez besoin que d'une application par page / document, mais si vous souhaitez exécuter plusieurs applications Angular (dont chacune peut utiliser un ou plusieurs modules) sur la même page / document, vous devrez alors amorcer manuellement chacune d'elles - - ne pas utiliser ng-app(car cela ne fonctionnera pas). ng-appne peut être utilisé qu'une seule fois par document HTML. Ce n'est vraiment qu'un raccourci si vous n'avez qu'une seule application sur la page, ce qui est le cas normal.
Mark Rajcok
1
Y a-t-il un exemple de cela? Je vois la documentation laconique de l'API boostrap mais je ne parviens pas à la faire fonctionner. J'ai googlé ceci pendant un moment et il ne semble pas y avoir un seul exemple fonctionnel. De plus, comment cela fonctionnerait-il avec les itinéraires? De toute évidence, il y a un problème de collision.
Robert Christian
De plus, j'aime beaucoup la façon dont l'utilisation de ng-app montre à un autre développeur exactement quelle partie de la page est contrôlée par quel module. N'existe-t-il aucun moyen d'utiliser le balisage sur la page pour accomplir cela? Ou du moins, un indice dans le balisage?
chrismarx
1
Les deux premiers paragraphes de la directive ng-app disent tout - docs.angularjs.org/api/ng.directive:ngApp
simo
38

J'ai créé une directive alternative qui n'a pas ngAppde limites. Ça s'appelle ngModule. Voici à quoi ressemblerait votre code lorsque vous l'utiliserez:

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

Vous pouvez obtenir le code source sur:

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

C'est essentiellement le même code utilisé en interne par AngularJS sans les limitations.

Luis Perez
la source
luisperezphd: J'ai lu votre article de blog. Existe-t-il un moyen d'imbriquer des applications (par exemple un générateur de widgets avec un widget chargé AJAX) ou de détecter si une page a déjà une application et d'injecter une autre application en tant que dépendance de la première? Je viens de poster ma question ici avec plus de détails sur exactement ce que j'essaie d'accomplir. Merci!
Daniel Bonnell du
@ACIDSTEALTH Le fait qu'AngularJS rapporte que l'élément déjà amorcé signifie qu'il doit y avoir un moyen de le dire - bien que ce code puisse être interne à AngularJS. Pour le savoir, vous pouvez référencer la version non réduite d'AngularJS et le point d'arrêt sur cette erreur pour voir la condition if. D'après ce que je peux faire de votre lien de question StackOverflow, il semble que vous vouliez "injecter" dynamiquement un module au moment de l'exécution. Si tel est le cas, vous voudrez peut-être jeter un œil à cet article: weblogs.asp.net/dwahlin/…
Luis Perez
Salut @LuisPerez, j'ai vérifié votre site Web. Je l'ai fatigué sur ma machine. angularJS ne détecte pas "ng-modules" / "ng-module". Ai-je besoin de références incluses dans mon dossier?
sujay kodamala
Oui @sujaykodamala, ngModule n'est pas intégré à AngularJS, c'est une directive que j'ai créée. Vous pouvez le télécharger depuis GitHub. Vous pouvez le trouver ici: github.com/luisperezphd/ngModule
Luis Perez
Bonjour @Luis Perez! Je vérifiais votre article de blog et ils sont vraiment géniaux. Si vous avez le temps, pourriez-vous consulter mon message ici pour résoudre un problème - stackoverflow.com/questions/46952478/… . Merci.
user8512043
19

Pourquoi voulez-vous utiliser plusieurs [ng-app]? Étant donné qu'Angular est repris à l'aide de modules, vous pouvez utiliser une application qui utilise plusieurs dépendances.

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>

ÉDITER

Gardez à l'esprit que si vous souhaitez utiliser le contrôleur à l'intérieur du contrôleur, vous devez utiliser la syntaxe controllerAs, comme ceci:

<div ng-app="app">
    <div ng-controller="AppController as app">
        <div ng-controller="OtherController as other">...</div>
    </div>
</div>
Monkey Monk
la source
Erreur non interceptée: [$ injector: modulerr] errors.angularjs.org/1.3.14/$injector/...… criptMinification% 2Fbower_components% 2Fangular% 2Fangular.min.js% 3A17% 3A381)
Anandaraja_Srinivasan
Avez-vous essayé d'inverser l'ordre des 2 modules? ('OtherModule' avant 'app') Parce que j'utilise beaucoup cette solution et cela fonctionne parfaitement ...
Monkey Monk
1
D'accord ! J'ai vu une erreur dans l'exemple Javascript que je fournis. Je pense que c'est corrigé maintenant! Pour mémoire, je vais utiliser la syntaxe setter à 2 endroits pour le même module ... ce qui n'est évidemment pas permis! :-)
Monkey Monk
la façon dont nous 'posons pour le faire
Harry Bosh
9

Vous pouvez amorcer plusieurs applications angulaires, mais:

1) Vous devez les amorcer manuellement

2) Vous ne devez pas utiliser "document" comme racine, mais le nœud où l'interface angulaire est contenue pour:

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

Ce serait sûr.

Wouter
la source
3

L'amorçage manuel des deux modules fonctionnera. Regarde ça

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

Voici le lien vers le Plunker http://plnkr.co/edit/1SdZ4QpPfuHtdBjTKJIu?p=preview

REMARQUE: en html, il n'y a pas de fichier ng-app. ida été utilisé à la place.

Hari Das
la source
0

J'ai créé un POC pour une application angulaire en utilisant plusieurs modules et sorties de routeur pour imbriquer des sous-applications dans une application d'une seule page. Vous pouvez obtenir le code source sur: https://github.com/AhmedBahet/ng-sub-apps

J'espère que cela aidera

abahet
la source