AngularJS Plusieurs ng-app dans une page

181

Je viens de commencer à apprendre Angular JS et j'ai créé quelques exemples de base, mais je suis coincé avec le problème suivant.

J'ai créé 2 modules et 2 contrôleurs.

shoppingCart -> ShoppingCartController
namesList -> NamesController

Il existe des vues associées pour chaque contrôleur. La première vue rend bien mais la seconde ne rend pas. Il n'y a pas d'erreurs.

http://jsfiddle.net/ep2sQ/

Veuillez m'aider à résoudre ce problème.

Il existe également une possibilité d'ajouter une console dans View pour vérifier les valeurs transmises par Controller.

par exemple, dans le div suivant, pouvons-nous ajouter console.log et afficher les valeurs du contrôleur

<div ng-app="shoppingCart" ng-controller="ShoppingCartController">
</div>
Nitin Mukesh
la source
10
peut-être que cela aidera: stackoverflow.com/questions/12860595/…
Ivan Chernykh
Merci Cherniv. Ceci est très utile et j'ai résolu le problème en utilisant le lien que vous avez fourni. Pourriez-vous également fournir des informations sur l'utilisation de console.log pour vider le contrôleur dans la vue / le modèle {{console.log}} ne fonctionne pas.
Nitin Mukesh
vous êtes le bienvenu. notez que vous faites déjà "console" dans une vue, ceci: en {{item.product_name}}fait "imprime" une valeur de votre modèle
Ivan Chernykh
1
Y a-t-il un problème avec la création de plusieurs applications pour une application Web? J'ai ce projet où chaque page html a sa propre application, je veux savoir si les performances seront affectées de toute façon?
SamAko
Bien qu'il soit possible de démarrer plusieurs applications AngularJS par page, nous ne testons pas activement ce scénario. Il est possible que vous rencontriez des problèmes, en particulier avec des applications complexes, donc la prudence est de mise. Voir AngularJS Developer Guide - Bootstrap .
georgeawg

Réponses:

190

Donc, fondamentalement, comme mentionné par Cherniv, nous devons amorcer les modules pour avoir plusieurs ng-app dans la même page. Merci beaucoup pour toutes les contributions.

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
la source
2
Vous pouvez créer une directive pour le faire à la place. Stackoverflow.com/a/22898036/984780
Luis Perez
33
La documentation angulaire indique que lors du démarrage manuel d'une application, NE PAS utiliser la directive ngApp. Donc ng-app = "namesList" (pourrait / devrait) être réoved. docs.angularjs.org/guide/bootstrap
Mike_K
4
Pour ceux qui ont des ng-app dans deux fichiers js séparés, le code ci-dessous pourrait aider angular.element (document) .ready (function () {angular.bootstrap (document.getElementById ("App2"), ['namesList']) ;});
Siva Kannan
3
Remarque: dans mon application, j'ai dû mettre cette ligne "angular.bootstrap (document.getElementById (" App2 "), ['namesList']);" dans la fonction $ (document) .ready
La masse
Cela ne fonctionne pas pour moi.Seule la première ng-app fonctionne correctement
SIVAKUMAR.J
120

Pour exécuter plusieurs applications dans un document HTML, vous devez les amorcer manuellement en utilisant 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 raison en est qu'une seule application AngularJS peut être automatiquement amorcée par document HTML. Le premier ng-apptrouvé dans le document sera utilisé pour définir l'élément racine à amorcer automatiquement en tant qu'application.

En d'autres termes, s'il est techniquement possible d'avoir plusieurs applications par page, une seule directive ng-app sera automatiquement instanciée et initialisée par le framework Angular.

AlwaysALearner
la source
20
Une seule ngAppdirective peut être amorcée automatiquement par document HTML, mais vous pouvez avoir plusieurs applications tant que vous amorcez manuellement les suivantes.
JaredMcAteer
@CodeHater où se namesListtrouve alors le module? Pourriez-vous mettre à jour votre réponse afin qu'elle soit plus claire?
Eugene
C'est faux. Vous POUVEZ avoir plusieurs ng-app. Voir stackoverflow.com/a/24867989/753632
AndroidDev
3
@AndroidDev, je ne suis pas. Le lien que vous référencez n'affiche pas plusieurs attributs ng-app.
Jpnh
42

Vous pouvez utiliser angular.bootstrap()directement ... le problème est que vous perdez les avantages des directives.

Vous devez d'abord obtenir une référence à l'élément HTML afin de l'amorcer, ce qui signifie que votre code est maintenant couplé à votre HTML.

Deuxièmement, l'association entre les deux n'est pas aussi évidente. Avec ngAppvous pouvez voir clairement quel HTML est associé à quel module et vous savez où chercher ces informations. Mais angular.bootstrap()peut être invoqué de n'importe où dans votre code.

Si vous voulez le faire, la meilleure façon serait d'utiliser une directive. C'est ce que j'ai fait. Ça s'appelle ngModule. Voici à quoi ressemblerait votre code en l'utilisant:

<!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 pour cela à:

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

Il est mis en œuvre de la même manière que ngApp. Il appelle simplement angular.bootstrap()les coulisses.

Luis Perez
la source
9

Dans mon cas, j'ai dû encapsuler le bootstrap de ma deuxième application angular.element(document).readypour que cela fonctionne:

angular.element(document).ready(function() {
  angular.bootstrap(document.getElementById("app2"), ["app2"]);
});   
Saeb Amini
la source
V1.6 obsolète: utilisez à la angular.element(callback)place de angular.element(document).ready(callback)). Voir AngularJS angular.element API Reference . Aussi github.com/angular/angular.js/commit/…
georgeawg
7

Voici un exemple de deux applications dans une page html et deux contrôleurs dans une 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>

merrais
la source
6

Vous pouvez fusionner plusieurs modules dans un rootModule et attribuer ce module en tant que ng-app à un élément supérieur ex: balise body.

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>
Vijay Tripathi
la source
4
Vous imbriquez deux applications différentes dans rootApp, Angular ne permet pas l'imbrication d'applications
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
la source
Juste une extension pour avoir plusieurs ng-app sur une seule page, je devais simplement combiner le code saeb-amini et @Nithin Mukesh - Merci à tous les deux
Praneeth
Ce concept fonctionne pour moi. angular.element (document) .ready (function () {angular.bootstrap (document.getElementById ("App2"), ['namesList']); angular.bootstrap (document.getElementById ("App3"), ['namesList2' ]);});
SIVAKUMAR.J
3

// 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
la source
2

Une seule application est automatiquement initialisée. D'autres doivent être initialisés manuellement comme suit:

Syntaxe:

angular.bootstrap(element, [modules]);

Exemple:

<!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
la source
1

Vous pouvez définir une ng-App racine et dans cette ng-App, vous pouvez définir plusieurs nd-Controler. Comme ça

    <!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
la source
0

J'ai modifié votre jsfiddle, je peux créer la plupart des modules en tant que rootModule pour le reste des modules. Ci-dessous Modifications mises à jour sur votre jsfiddle.

  1. Le deuxième module peut être injecté dans RootModule.
  2. En Html, la deuxième ng-app définie est placée dans la racine ng-app.

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

Mano
la source
Une idée pourquoi cela évalue seulement le premier ng-app? jsfiddle.net/vwcbtzdg
Si8
D'abord seulement initialisé automatiquement, les autres doivent s'initialiser manuellement
Mano
0

Utilisez angular.bootstrap(element, [modules], [config])pour démarrer manuellement l'application AngularJS (pour plus d'informations, consultez le guide Bootstrap ).

Consultez l'exemple suivant:

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

Oui
la source
-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
la source
1
Ajoutez une description à votre réponse ce que vous avez publié
Abhinav Singh Maurya
1
Besoin de commentaires expliquant ce qui se passe! Bien essayé!
Eric Brown - Cal