Wie definiere ich zwei eckige Apps / Module auf einer Seite?


118

Ich versuche, einer Seite zwei eckige Apps / Module hinzuzufügen. In den folgenden Geigen sehen Sie, dass immer nur das erste Modul, auf das im HTML-Code verwiesen wird, ordnungsgemäß funktioniert, während das zweite Modul nicht durch Winkel erkannt wird.

In dieser Geige können wir nur die doSearch2Methode ausführen , während in dieser Geige nur die doSearchMethode korrekt funktioniert.

Ich suche nach einer Möglichkeit, zwei Winkelmodule korrekt auf einer Seite zu platzieren.

Antworten:


123

Pro HTML-Dokument kann nur eine AngularJS-Anwendung automatisch gebootet werden. Die erste im Dokument gefundene ngApp wird verwendet, um das Stammelement für den automatischen Bootstrap als Anwendung zu definieren. Um mehrere Anwendungen in einem HTML-Dokument auszuführen, müssen Sie sie stattdessen manuell mit angle.bootstrap booten. AngularJS-Anwendungen können nicht ineinander verschachtelt werden. - http://docs.angularjs.org/api/ng.directive:ngApp

Siehe auch


@MarkRajcok Ist es also eine gute Praxis, nur ein Modul pro HTML-Dokument zu haben? Das Beispiel "Wire up a Backend" auf der AngularJS-Hauptseite enthält ng-app="project"und besagt, dass "damit Module in verschiedenen Teilen der Seite ausgeführt werden können", das ngApp-Dokument jedoch angibt, dass "nur eine Direktive pro HTML-Dokument verwendet werden kann".
Theblang

9
@mattblang, Module sind Angular-Anwendungen zugeordnet und nicht wirklich HTML-Dokumenten. Normalerweise benötigen Sie nur eine App pro Seite / Dokument. Wenn Sie jedoch mehrere Angular-Anwendungen (von denen jede ein oder mehrere Module verwenden kann) auf derselben Seite / demselben Dokument ausführen möchten, müssen Sie jede von ihnen manuell booten. - nicht verwenden ng-app(weil es nicht funktioniert). ng-appkann nur einmal pro HTML-Dokument verwendet werden. Es ist wirklich nur eine Abkürzung, wenn Sie nur eine App auf der Seite haben, was der Normalfall ist.
Mark Rajcok

1
Gibt es ein Beispiel dafür? Ich sehe die knappe Boostrap-API-Dokumentation, kann sie aber nicht zum Laufen bringen. Ich habe das eine Weile gegoogelt und es scheint kein einziges funktionierendes Beispiel zu geben. Wie in aller Welt würde dies außerdem mit Routen funktionieren? Offensichtlich gibt es ein Kollisionsproblem.
Robert Christian

Außerdem gefällt mir sehr, wie die Verwendung von ng-app einem anderen Entwickler genau zeigt, welcher Teil der Seite von welchem ​​Modul gesteuert wird. Gibt es keine Möglichkeit, Markup auf der Seite zu verwenden, um dies zu erreichen? Oder zumindest ein Hinweis im Markup?
Chrismarx

1
Die ersten beiden Absätze für die ng-app-Direktive sagen alles - docs.angularjs.org/api/ng.directive:ngApp
simo

38

Ich habe eine alternative Direktive erstellt, die keine ngAppEinschränkungen hat. Es heißt ngModule. So würde Ihr Code aussehen, wenn Sie ihn verwenden:

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

Den Quellcode erhalten Sie unter:

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

Es ist im Wesentlichen derselbe Code, der von AngularJS intern ohne Einschränkungen verwendet wird.


luisperezphd: Ich habe deinen Blog-Beitrag gelesen. Gibt es eine Möglichkeit, Apps zu verschachteln (z. B. einen Widget-Builder mit einem von AJAX geladenen Widget) oder zu erkennen, ob eine Seite bereits eine App enthält, und eine andere App als Abhängigkeit von der ersten einzufügen? Ich habe gerade meine Frage hier mit genaueren Angaben zu dem, was ich erreichen möchte, gepostet . Vielen Dank!
Daniel Bonnell

@ACIDSTEALTH Die Tatsache, dass AngularJS meldet, dass das Element bereits gebootet wurde, bedeutet, dass es eine Möglichkeit geben muss, dies zu erkennen - obwohl dieser Code möglicherweise AngularJS-intern ist. Um dies herauszufinden, können Sie auf die nicht minimierte Version von AngularJS und den Haltepunkt für diesen Fehler verweisen, um die if-Bedingung anzuzeigen. Nach dem, was ich aus Ihrem StackOverflow-Fragenlink ersehen kann, klingt es so, als ob Sie ein Modul zur Laufzeit dynamisch "injizieren" möchten. Wenn ja, möchten Sie vielleicht einen Blick auf diesen Artikel werfen
Luis Perez

Hey @LuisPerez, ich habe deine Website überprüft. Ich habe es auf meiner Maschine müde gemacht. angleJS erkennt "ng-modules" / "ng-module" nicht. Benötige ich Referenzen in meiner Datei?
Sujay Kodamala

Ja @sujaykodamala, ngModule ist nicht in AngularJS integriert, sondern eine von mir erstellte Direktive. Sie können es von GitHub herunterladen. Sie finden es hier: github.com/luisperezphd/ngModule
Luis Perez

Hallo @Luis Perez! Ich habe Ihren Blog-Beitrag überprüft und sie sind wirklich großartig. Wenn Sie Zeit haben, können Sie bitte meinen Beitrag hier überprüfen, um ein Problem zu beheben - stackoverflow.com/questions/46952478/… . Vielen Dank.
user8512043

19

Warum möchten Sie mehrere [ng-app] verwenden? Da Angular mithilfe von Modulen wieder aufgenommen wird, können Sie eine App verwenden, die mehrere Abhängigkeiten verwendet.

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>

BEARBEITEN

Beachten Sie, dass Sie, wenn Sie den Controller innerhalb des Controllers verwenden möchten, die ControllerAs-Syntax wie folgt verwenden müssen:

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

Nicht erfasster Fehler: [$ injor: modulerr] error.angularjs.org/1.3.14/$injector/…… criptMinification% 2Fbower_components% 2Fangular% 2Fangular.min.js% 3A17% 3A381)
Anandaraja_Srinivasan

Haben Sie versucht, die Reihenfolge der beiden Module umzukehren? ('OtherModule' vor 'app') Weil ich diese Lösung häufig benutze und sie perfekt funktioniert ...
Monkey Monk

1
OK ! Ich habe einen Fehler in dem von mir bereitgestellten Javascript-Beispiel gesehen. Ich denke es ist jetzt behoben! Für die Aufzeichnung werde ich die Setter-Syntax an 2 Stellen für dasselbe Modul verwenden ... was offensichtlich nicht erlaubt ist! :-)
Monkey Monk

so wie wir es uns vorstellen
Harry Bosh

9

Sie können mehrere Winkelanwendungen booten, aber:

1) Sie müssen sie manuell booten

2) Sie sollten nicht "document" als Root verwenden, sondern den Knoten, in dem sich die Winkelschnittstelle befindet, um:

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

Das wäre sicher.


3

Das manuelle Bootstrapping beider Module funktioniert. Schau dir das an

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

Hier ist der Link zum Plunker http://plnkr.co/edit/1SdZ4QpPfuHtdBjTKJIu?p=preview

HINWEIS: In HTML gibt es keine ng-app. idwurde stattdessen verwendet.


0

Ich habe einen POC für eine Angular-Anwendung erstellt, indem ich mehrere Module und Router-Outlets verwendet habe, um Unter-Apps in einer App mit nur einer Seite zu verschachteln. Den Quellcode erhalten Sie unter: https://github.com/AhmedBahet/ng-sub-apps

Hoffe das wird helfen

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.