Jak zdefiniować dwie aplikacje / moduły Angular na jednej stronie?


118

Próbuję dodać dwie aplikacje / moduły kątowe do jednej strony. Na poniższych skrzypcach widać, że zawsze tylko pierwszy moduł, do którego odwołuje się kod html, będzie działał poprawnie, podczas gdy drugi nie jest rozpoznawany przez angular.

Na tych skrzypcach możemy wykonać tylko doSearch2metodę, podczas gdy na tych skrzypcach tylko doSearchmetoda działa poprawnie.

Szukam sposobu, jak poprawnie umieścić dwa kątowe moduły na jednej stronie.

Odpowiedzi:


123

Tylko jedna aplikacja AngularJS może zostać automatycznie załadowana na dokument HTML. Pierwsza aplikacja ngApp znaleziona w dokumencie zostanie użyta do zdefiniowania elementu głównego do automatycznego ładowania jako aplikacji. Aby uruchomić wiele aplikacji w dokumencie HTML, należy ręcznie załadować je za pomocą angular.bootstrap. Aplikacje AngularJS nie mogą być zagnieżdżane w sobie. - http://docs.angularjs.org/api/ng.directive:ngApp

Zobacz też


@MarkRajcok Czy więc dobrą praktyką jest posiadanie tylko jednego modułu na dokument HTML? Przykład „Podłącz zaplecze” na głównej stronie AngularJS określa ng-app="project"i mówi, że „pozwala to mieć moduły działające w różnych częściach strony”, ale dokument ngApp stwierdza, że ​​„tylko jedna dyrektywa może być używana na dokument HTML”.
theblang

9
@mattblang, moduły są powiązane z aplikacjami Angular, a nie dokumentami HTML. Zwykle potrzebujesz tylko jednej aplikacji na stronę / dokument, ale jeśli chcesz uruchomić wiele aplikacji Angular (z których każda może używać jednego lub więcej modułów) na tej samej stronie / dokumencie, musisz ręcznie załadować każdą z nich - - nie używaj ng-app(bo to nie zadziała). ng-appmoże być użyty tylko raz na dokument HTML. To naprawdę jest tylko skrót, jeśli masz tylko jedną aplikację na stronie, co jest normalnym przypadkiem.
Mark Rajcok

1
Czy jest na to przykład? Widzę zwięzłą dokumentację boostrap api, ale nie mogę jej uruchomić. Przeglądałem to przez jakiś czas i wydaje się, że nie ma ani jednego działającego przykładu. Poza tym, jak na świecie miałoby to działać z trasami? Oczywiście istnieje problem kolizji.
Robert Christian

Poza tym bardzo podoba mi się sposób, w jaki używanie ng-app pokazuje innemu deweloperowi dokładnie, która część strony jest kontrolowana przez jaki moduł. Czy nie ma sposobu, aby użyć znaczników na stronie, aby to osiągnąć? A przynajmniej jakąś wskazówkę w znacznikach?
chrismarx

1
Pierwsze dwa akapity dyrektywy ng-app mówią wszystko - docs.angularjs.org/api/ng.directive:ngApp
simo

38

Stworzyłem alternatywną dyrektywę, która nie ma ngAppograniczeń. To się nazywa ngModule. Tak wyglądałby kod, gdy go używasz:

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

Możesz pobrać kod źródłowy pod adresem:

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

Zasadniczo jest to ten sam kod, który jest używany wewnętrznie przez AngularJS bez ograniczeń.


luisperezphd: Czytałem twój wpis na blogu. Czy istnieje sposób na zagnieżdżenie aplikacji (np. Narzędzie do tworzenia widżetów z widżetem załadowanym AJAX) lub wykrycie, czy strona ma już aplikację i wstrzyknięcie innej aplikacji jako zależności od pierwszej? Właśnie zamieściłem tutaj moje pytanie z dokładniejszymi szczegółami tego, co próbuję osiągnąć. Dzięki!
Daniel Bonnell,

@ACIDSTEALTH Fakt, że AngularJS zgłasza, że ​​element został już załadowany, oznacza, że ​​musi istnieć jakiś sposób, aby to stwierdzić - chociaż ten kod może być wewnętrzny dla AngularJS. Aby się dowiedzieć, możesz odwołać się do niezminifikowanej wersji AngularJS i punktu przerwania tego błędu, aby zobaczyć warunek if. Z tego, co widzę z linku do pytania StackOverflow, wygląda na to, że chcesz dynamicznie „wstrzyknąć” moduł w czasie wykonywania. Jeśli tak, warto przyjrzeć się tym artykułem: weblogs.asp.net/dwahlin/...
Luis Perez

Hej @LuisPerez, sprawdziłem twoją stronę internetową. Zmęczyłem to na mojej maszynie. angularJS nie wykrywa "ng-modules" / "ng-module". Czy muszę mieć jakieś referencje zawarte w moim pliku?
sujay kodamala

Tak @sujaykodamala, ngModule nie jest wbudowany w AngularJS, to jest dyrektywa, którą stworzyłem. Możesz go pobrać z GitHub. Możesz go znaleźć tutaj: github.com/luisperezphd/ngModule
Luis Perez

Witaj @Luis Perez! Sprawdzałem twój post na blogu i są naprawdę niesamowite. Jeśli masz czas, czy możesz sprawdzić mój post tutaj, aby rozwiązać problem - stackoverflow.com/questions/46952478/… . Dzięki.
user8512043

19

Dlaczego chcesz używać wielu [ng-app]? Ponieważ Angular jest wznawiany przy użyciu modułów, możesz użyć aplikacji, która używa wielu zależności.

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>

EDYTOWAĆ

Pamiętaj, że jeśli chcesz używać kontrolera wewnątrz kontrolera, musisz użyć składni controllerAs, na przykład:

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

Uncaught Error: [$ injector: modulerr] errors.angularjs.org/1.3.14/$injector/…… criptMinification% 2Fbower_components% 2Fangular% 2Fangular.min.js% 3A17% 3A381)
Anandaraja_Srinivasan

Czy próbowałeś odwrócić kolejność 2 modułów? ('OtherModule' przed 'app') Ponieważ często korzystam z tego rozwiązania i działa idealnie ...
Monkey Monk

1
Dobrze ! Widziałem błąd w podanym przeze mnie przykładzie Javascript. Myślę, że teraz jest to naprawione! Dla przypomnienia, użyję składni ustawiającej w 2 miejscach dla tego samego modułu ... co oczywiście jest niedozwolone! :-)
Monkey Monk

sposób, w jaki to robimy
Harry Bosh

9

Możesz załadować wiele aplikacji kątowych, ale:

1) Musisz ręcznie załadować je

2) Nie należy używać „document” jako katalogu głównego, ale węzeł, w którym znajduje się interfejs kątowy, do:

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

To byłoby bezpieczne.


3

Ręczne ładowanie obu modułów będzie działać. Spójrz na to

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

Oto link do Plunkera http://plnkr.co/edit/1SdZ4QpPfuHtdBjTKJIu?p=preview

UWAGA: w html nie ma ng-app. idzostał użyty zamiast tego.


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.