AngularJS Vários aplicativos ng dentro de uma página

180

Eu apenas comecei a aprender o Angular JS e criei alguns exemplos básicos, no entanto, estou com o seguinte problema.

Eu criei 2 módulos e 2 controladores.

shoppingCart -> ShoppingCartController
namesList -> NamesController

Existem visualizações associadas para cada controlador. A primeira exibição é renderizada, mas a segunda não é renderizada. Não há erros.

http://jsfiddle.net/ep2sQ/

Ajude-me a resolver esse problema.

Também existe a possibilidade de adicionar console no modo de exibição para verificar quais valores são transmitidos do Controller.

Por exemplo, na div a seguir, podemos adicionar console.log e gerar os valores do controlador

<div ng-app="shoppingCart" ng-controller="ShoppingCartController">
</div>
Nitin Mukesh
fonte
10
pode ser que isso ajude: stackoverflow.com/questions/12860595/…
Cherniv
Obrigado Cherniv. Isso é muito útil e resolvi o problema usando o link que você forneceu. Você também pode fornecer informações sobre como usar o console.log para despejar o Controller em View / Template {{console.log}} não está funcionando.
Nitin Mukesh
bem vindo. nota que você já está fazendo "console" em uma vista, este: {{item.product_name}}na verdade, "impressões" um valor de seu modelo
Cherniv
1
Há algo de errado em criar vários aplicativos para um webapp? Eu tenho esse projeto em que cada página html possui seu próprio aplicativo. Quero saber se o desempenho será afetado de qualquer maneira?
T. Rex
Embora seja possível inicializar mais de um aplicativo AngularJS por página, não testamos ativamente esse cenário. É possível que você tenha problemas, especialmente com aplicativos complexos, por isso é recomendável cautela. Consulte o Guia do desenvolvedor do AngularJS - Bootstrap .
georgeawg

Respostas:

190

Então, basicamente, como mencionado por Cherniv, precisamos inicializar os módulos para ter vários aplicativos ng dentro da mesma página. Muito obrigado por todas as 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
fonte
2
Você pode criar uma directiva para fazer isso em vez stackoverflow.com/a/22898036/984780
Luis Perez
33
A documentação angular diz que, ao inicializar manualmente um aplicativo, NÃO use a diretiva ngApp. Então ng-app = "namesList" (poderia / deveria) ser removido. docs.angularjs.org/guide/bootstrap
Mike_K
4
Para aqueles que possuem ng-app em dois arquivos js separados, o código abaixo pode ajudar angular.element (document) .ready (function () {angular.bootstrap (document.getElementById ("App2"), ['namesList'])) ;});
Siva Kannan
3
Nota: no meu aplicativo, tive que colocar esta linha "angular.bootstrap (document.getElementById (" App2 "), ['namesList']));" na função $ (document) .ready
La masse
O aplicativo ng-app funciona corretamente
SIVAKUMAR.J
120

Para executar vários aplicativos em um documento HTML, você deve inicializá-los manualmente usando 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']);

A razão para isso é que apenas um aplicativo AngularJS pode ser inicializado automaticamente por documento HTML. O primeiro ng-appencontrado no documento será usado para definir o elemento raiz para auto-inicialização como um aplicativo.

Em outras palavras, embora seja tecnicamente possível ter vários aplicativos por página, apenas uma diretiva ng-app será instanciada e inicializada automaticamente pela estrutura Angular.

AlwaysALearner
fonte
20
Somente uma ngAppdiretiva pode ser carregada automaticamente por documento HTML, mas você pode ter vários aplicativos, desde que inicie manualmente os subsequentes.
JaredMcAteer
@ CodeHater, onde está namesListlocalizado o módulo? Você poderia atualizar sua resposta, para que fique mais clara?
Eugene
Isto está errado. Você pode ter vários aplicativos ng. Veja stackoverflow.com/a/24867989/753632
AndroidDev
3
@AndroidDev, eu não sigo. O link que você faz referência não mostra vários atributos do aplicativo ng.
Jpnh
42

Você pode usar angular.bootstrap()diretamente ... o problema é que você perde os benefícios das diretivas.

Primeiro, você precisa obter uma referência ao elemento HTML para inicializá-lo, o que significa que seu código agora está acoplado ao seu HTML.

Em segundo lugar, a associação entre os dois não é tão aparente. Com ngAppvocê, você pode ver claramente qual HTML está associado a qual módulo e você sabe onde procurar essas informações. Mas angular.bootstrap()pode ser invocado de qualquer lugar no seu código.

Se você for fazer da melhor maneira possível, use uma diretiva. Foi o que eu fiz. É chamado ngModule. Aqui está a aparência do seu código usando-o:

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

Você pode obter o código fonte para isso em:

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

É implementado da mesma maneira que ngApp. Simplesmente chama angular.bootstrap()nos bastidores.

Luis Perez
fonte
9

No meu caso, tive que envolver o bootstrap do meu segundo aplicativo angular.element(document).readypara que ele funcionasse:

angular.element(document).ready(function() {
  angular.bootstrap(document.getElementById("app2"), ["app2"]);
});   
Saeb Amini
fonte
V1.6 Descontinuado: use em angular.element(callback)vez de angular.element(document).ready(callback)). Consulte Referência da API angularJS angular.element . Também github.com/angular/angular.js/commit/…
georgeawg
7

Aqui está um exemplo de dois aplicativos em uma página html e de dois controladores em um aplicativo:

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

Você pode mesclar vários módulos em um rootModule e atribuir esse módulo como ng-app a um elemento superior ex: body tag.

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
fonte
4
Você está nidificação dois aplicativos diferentes dentro do rootApp, não angular não permite aninhamento de aplicativos
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
fonte
Apenas uma extensão de ter múltiplos ng-app em uma única página que eu tinha apenas combinar código @Nithin Mukesh saeb-Amini e - Obrigado a ambos
Praneeth
Este conceito está funcionando para mim. angular.element (document) .ready (function () {angular.bootstrap (document.getElementById ("App2"), ['namesList']); angular.bootstrap (document.getElementById ("App3"), ['namesList2' ]);});
precisa saber é o seguinte
2

Somente um aplicativo é inicializado automaticamente. Outros precisam inicializar manualmente da seguinte maneira:

Sintaxe:

angular.bootstrap(element, [modules]);

Exemplo:

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

Você pode definir um ng-App raiz e neste ng-App você pode definir vários nd-Controler. Como isso

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

Eu modifiquei o seu jsfiddle, pode fazer o módulo mais top como rootModule para o resto dos módulos. Abaixo Modificações atualizadas no seu jsfiddle.

  1. O segundo módulo pode ser injetado no RootModule.
  2. Em HTML, o segundo aplicativo ng definido é colocado dentro do aplicativo raiz.

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

Mano
fonte
Alguma idéia de por que isso está avaliando apenas o primeiro ng-app? jsfiddle.net/vwcbtzdg
Si8
Primeiro única inicializado automaticamente, outro tem que manualmente initialize
Mano
0

Use angular.bootstrap(element, [modules], [config])para iniciar manualmente o aplicativo AngularJS (para obter mais informações, consulte o guia Bootstrap ).

Veja o seguinte exemplo:

// 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
fonte
-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
fonte
1
Adicione descrição à sua resposta o que você postou
Abhinav Singh Maurya
1
Precisa de comentários explicando o que está acontecendo! Boa tentativa!
Eric Brown - Cal