2013-05-24 10 views
8

Mam przypadek użycia, który wymaga załadowania osobnych aplikacji kątowych.Wiele aplikacji Angularjs (jazda portletów)

Na podstawie kilku pytań przepełnienia stosu i this google thread, jest to wykonalne. Jednak nie mogę go uruchomić.

Patrząc na dokumentacji:

http://docs.angularjs.org/api/angular.bootstrap

Wygląda na to trzeba dostarczyć element (co jest właściwym sposobem, aby uzyskać uchwyt na elemencie?), A następnie w jaki sposób powiązać ją z powrotem do konfiguracji, kontrolerów itp. A jak by to działało w przypadku tras? IE jak działa kolizja, tj. Aplikacja ai aplikacja b map/foo do /fooa.html i /foob.html odpowiednio ... lub każda z aplikacji sama się opisuje.

Dzięki!

+0

Czy to naprawdę dwie różne aplikacje, czy są to różne ścieżki routingu/różne widoki w ramach jednej aplikacji. Pytam, ponieważ dużo mówi się o temacie i doprowadziło to do stworzenia świetnego alternatywnego routera https://github.com/angular-ui/ui-router, który obsługuje złożone trasy i przepływy kontroli. Podobnie jak widok równoległy ustawia te ścieżki tras. –

+0

Z chęcią przeprowadzę Cię przez procedurę korzystania z tego w przypadku, który przedstawisz w poniższej odpowiedzi. O ile Twoje wymagania nie dotyczą w pełni ładowania poszczególnych aplikacji. –

+0

To dosłownie wiele aplikacji. Wyobraźmy sobie środowisko SOA, w którym usługi są wdrażane na różnych hostach, z których każdy ma stosunkowo prostą aplikację kątową UI (do konfiguracji tej konkretnej usługi). I aplikacja centralizująca (think admin portal/system console), która wie o każdym z nich i może przekopać się (uruchomić) swoją aplikację bez przekierowania. Zrobione w ten sposób, usługa może być zarządzana bezpośrednio, a także zarządzana za pośrednictwem interfejsu głównego. –

Odpowiedz

8

Tak więc, biorąc pod uwagę wymóg, że jest to treść serwisowa, jedynym sposobem, w jaki mogę to zobaczyć, jest mieszanka praktyk kątowych i standardowych html. W efekcie zechcesz pobrać stronę z książki plunker i użyć elementów iframe do przechowywania poszczególnych portletów.

<!doctype html> <html lang="en"> 

<body ng-app="plunker" ng-controller="MainCtrl"> 

<!-- define foo --> 

<div> 
    <ul class="menu"> 
     <li><a href="#" ng-click="fooRoute='#/foo1'">foo1</a></li> 
     <li><a href="#" ng-click="fooRoute='#/foo2'">foo2</a></li> 
    </ul> 
    <iframe seamless="true" ng-src="foo.index.html{{fooRoute}}"></iframe> </div> 

<div> 
    <ul class="menu"> 
     <li><a href="#" ng-click="barRoute='#/bar1'">bar1</a></li> 
     <li><a href="#" ng-click="barRoute='#/bar2'">bar2</a></li> 
    </ul> 
    <iframe seamless="true" ng-src="bar.index.html{{barRoute}}"></iframe> </div> 


<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.min.js"></script> <script src="app.js"></script> </body> </html> 

Następnie na każdym z tych portletów będziemy chcieli mieć całkowicie odrębny wniosek (wraz z załadunkiem zasobów).

<!doctype html> 
<html lang="en"> 

<body ng-app="fooApp"> 

<div ng-view></div> 


<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.min.js"></script> 
<script> 
    var app = angular.module('fooApp', ['fooApp.controllers']); 

    // Configure the app 
    app.config(['$routeProvider', function ($routeProvider) { 
     $routeProvider.when('/foo1', {template: '<h1>Foo</h1><h2>foo1</h2>', controller: 'MyCtrl1'}); 
     $routeProvider.when('/foo2', {template: '<h1>Foo</h1><h2>foo2</h2>', controller: 'MyCtrl2'}); 
    }]); 

    angular.module('fooApp.controllers', []). 
      controller('MyCtrl1', [function() { 
       console.log("fooApp.MyCtrl1 invoked."); 
      }]) 
      .controller('MyCtrl2', [function() { 
       console.log("fooApp.MyCtrl2 invoked."); 
      }]); 
</script> 
</body> 
</html> 

Jest to nieco mniej efektywne przy ładowaniu niż przy użyciu wspólnej bazy aplikacji, ale obecnie jest to niewykonalne. W zespole ui-routera angular-ui jest rozmowa na temat kontrolowania niezależnych widoków, które mogą być dla ciebie użyteczne, ale obecnie nie jest zaimplementowana, możesz śledzić dyskusję pod numerem https://github.com/angular-ui/ui-router/issues/84 i głosować zgodnie z twoją potrzebą. Istnieje również problem związany z tym problemem na liście problemów interfejsu użytkownika pod adresem https://github.com/angular-ui/ui-router/issues/160.

plunker Praca z tym wzorem: http://plnkr.co/edit/sPoK3I?p=preview

+0

Dzięki! Myślę, że to najlepsza odpowiedź dla mojego przypadku użycia. –

0

Więc masz 2 opcje tutaj: jeśli tworzysz je jako angular.module() nie byłoby sposobem atm łączenia modułów ze sobą.

jeśli tworzysz dyrektyw z templateURL do LazyLoad komponentów można nadawać współdzielonych atrybuty i słuchać ich i można wykorzystać te same usługi w swojej aplikacji. Prawdopodobnie byłoby to najlepsze dla ciebie.

+0

Odpowiedź będzie bliższa temu http://stackoverflow.com/questions/12860595/how-to-define-two--single-apps-modules-in-one-page. –

1

Wyliczyłem to. Oto sposób jednoczesnego ładowania dwóch aplikacji kątowych. patrz również, że nazwałem kontrolery takie same dla każdej aplikacji, aby pokazać, że Zależności nie będą kolidować (ponieważ są one scoped ramach każdej odpowiedniej aplikacji poprzez moduł):

<!doctype html> 
<html lang="en"> 

<body> 

<script src="lib/angular/angular.js"></script> 

<!-- define foo --> 

<div id="fooApp"> 

    <ul class="menu"> 
     <li><a href="#/foo1">foo1</a></li> 
     <li><a href="#/foo2">foo2</a></li> 
    </ul> 
    <div ng-view> 
    </div> 

</div> 

<script> 
    // Declare app level module which depends on filters, and services 
    var app = angular.module('fooApp', ['fooApp.controllers']); 

    // Configure the app 
    app.config(['$routeProvider', function ($routeProvider) { 
     $routeProvider.when('/foo1', {template: '<h1>Foo</h1><h2>foo1</h2>', controller: 'MyCtrl1'}); 
     $routeProvider.when('/foo2', {template: '<h1>Foo</h1><h2>foo2</h2>', controller: 'MyCtrl2'}); 
    }]); 

    angular.module('fooApp.controllers', []). 
      controller('MyCtrl1', [function() { 
       console.log("fooApp.MyCtrl1 invoked."); 
      }]) 
      .controller('MyCtrl2', [function() { 
       console.log("fooApp.MyCtrl2 invoked."); 
      }]); 

    // manually bootstrap 
    var div = document.getElementById('fooApp'); 
    console.log(div); 
    angular.bootstrap(div, ['fooApp']); 


</script> 


<!-- define bar --> 

<div id="barApp"> 

    <ul class="menu"> 
     <li><a href="#/bar1">bar1</a></li> 
     <li><a href="#/bar2">bar2</a></li> 
    </ul> 
    <div ng-view> 
    </div> 

</div> 

<script> 
    // Declare app level module which depends on filters, and services 
    var app = angular.module('barApp', ['barApp.controllers']); 

    // Configure the app 
    app.config(['$routeProvider', function ($routeProvider) { 
     $routeProvider.when('/bar1', {template: '<h1>Bar</h1><h2>bar1</h2>', controller: 'MyCtrl1'}); 
     $routeProvider.when('/bar2', {template: '<h1>Bar</h1><h2>bar2</h2>', controller: 'MyCtrl2'}); 
    }]); 

    angular.module('barApp.controllers', []). 
      controller('MyCtrl1', [function() { 
       console.log("barApp.MyCtrl1 invoked."); 
      }]) 
      .controller('MyCtrl2', [function() { 
       console.log("barApp.MyCtrl2 invoked."); 
      }]); 


    // manually bootstrap 
    var div = document.getElementById('barApp'); 
    console.log(div); 
    angular.bootstrap(div, ['barApp']); 
</script> 


</body> 

</html> 

Jedyne pytanie brzmi: jak radzić sobie z kolizjami routingu .

+0

pokonałeś mnie! Bądź ostrożny z routing tho. "Inaczej()' bolało naprawdę źle. Możesz również użyć 'ready' do bootstrap:' angular.element (document) .ready (function() {angular.bootstrap (document, ['app1']);}); ' – Ven

+0

Dzięki. Powyższa odpowiedź jest tylko pierwszym krokiem. Teraz muszę odpowiedzieć "jak obsługiwać/zapobiegać kolizjom w routeProvider." –

+0

Zasadniczo - nie musisz. Myślę, że trochę utknąłeś tutaj, routery-ui's router może pomóc państwom itp., Ale tak naprawdę jedyne co mogę myśleć to umieścić jedną aplikację w html5Mode, a drugą z html5Mode off. – Ven

2

Ok więc ja zorientowali się, jak to zrobić za pomocą kątowego UI-routera kluczem sprowadza się do zdolności kątowego UI-router przejściowym stany bez wpływu URL .

Kroki, aby dostać tę pracę

  • Pierwszą instancję każda aplikacja jako samodzielna aplikacja z wykorzystaniem ręczną bootstrap do Zidentyfikowaliśmy elementu.
  • Dołącz do każdego aplikatora routery $ stanProvider do sterowania wewnętrznymi przejściami stanu (trasami).
    • Należy tutaj pozostawić klucz url dla każdego zdefiniowanego stanu lub zresetować stronę, zmieniając adres URL przy każdym przejściu stanu.
  • Skonfiguruj funkcję stanu w sterowniku głównym, aby sterować zmianami stanu.

Poniżej znajduje się kod, aby uzyskać tej pracy:

<!DOCTYPE html> 
<html ng-app="plunker"> 

    <head> 
    <meta charset="utf-8" /> 
    <title>AngularJS Plunker</title> 
    <script>document.write('<base href="' + document.location + '" />');</script> 
    <link rel="stylesheet" href="style.css" /> 
    <script data-require="[email protected]" src="http://code.angularjs.org/1.0.7/angular.min.js" data-semver="1.0.7"></script> 
    <script src="angular-ui-states.min.js"></script> 
    <script src="app.js"></script> 
    </head> 
<!-- define foo --> 

<div id="fooApp" ng-controller="MainCtrl"> 

    <ul class="menu"> 
     <li><a href="#" ng-click="state('foo1')">foo1</a></li> 
     <li><a href="#" ng-click="state('foo2')">foo2</a></li> 
    </ul> 
    <div ui-view> 
    </div> 

</div> 

<script> 
    // Declare app level module which depends on filters, and services 
    var app = angular.module('fooApp', ['fooApp.controllers', 'ui.state']); 

    // Configure the app 
    app.config(['$stateProvider', function ($stateProvider) { 
     $stateProvider 
      .state('foo1', 
      { 
      template: '<h1>Foo</h1><h2>foo1</h2>', 
      controller: 'MyCtrl1' 
      }) 
      .state('foo2', 
      { 
      template: '<h1>Foo</h1><h2>foo2</h2>', 
      controller: 'MyCtrl2' 
      }); 
    }]); 

    angular.module('fooApp.controllers', []) 
      .controller('MainCtrl', ['$scope', '$state', function($scope, $state){ 
       $scope.state = function(name){ 
       console.log('Transition to state ' + name); 
       $state.transitionTo(name); 
       } 
      }]) 
      .controller('MyCtrl1', [function() { 
       console.log("fooApp.MyCtrl1 invoked."); 
      }]) 
      .controller('MyCtrl2', [function() { 
       console.log("fooApp.MyCtrl2 invoked."); 
      }]); 

    // manually bootstrap 
    var div = document.getElementById('fooApp'); 
    console.log(div); 
    angular.bootstrap(div, ['fooApp']); 


</script> 


<!-- define bar --> 

<div id="barApp" ng-controller="MainCtrl"> 

    <ul class="menu"> 
     <li><a href="#" ng-click="state('bar1')">bar1</a></li> 
     <li><a href="#" ng-click="state('bar2')">bar2</a></li> 
    </ul> 
    <div ui-view> 
    </div> 

</div> 

<script> 
    // Declare app level module which depends on filters, and services 
    var app = angular.module('barApp', ['barApp.controllers', 'ui.state']); 


    app.config(['$stateProvider', function ($stateProvider) { 
     $stateProvider 
      .state('bar1', 
      { 
      template: '<h1>Bar</h1><h2>bar1</h2>', 
      controller: 'MyCtrl1' 
      }) 
      .state('bar2', 
      { 
      template: '<h1>Bar</h1><h2>bar2</h2>', 
      controller: 'MyCtrl2' 
      }); 
    }]); 

    angular.module('barApp.controllers', []) 
      .controller('MainCtrl', ['$scope', '$state', function($scope, $state){ 
       $scope.state = function(name){ 
       console.log('Transition to state ' + name); 
       $state.transitionTo(name); 
       } 
      }]) 
      .controller('MyCtrl1', [function() { 
       console.log("barApp.MyCtrl1 invoked."); 
      }]) 
      .controller('MyCtrl2', [function() { 
       console.log("barApp.MyCtrl2 invoked."); 
      }]); 

    // manually bootstrap 
    var div = document.getElementById('barApp'); 
    console.log(div); 
    angular.bootstrap(div, ['barApp']); 
</script> 


</body> 

</html> 

plunker tego roztworu roboczego w http://plnkr.co/edit/bXSN8qSMdioZJLYs2zyk?p=preview

Proszę zobaczyć mój poprzedni odpowiedź do dyskusji aktualnie występujących aby wsparcie portlet bardziej nieodłącznym w ui-routerze.

+0

To jest bardzo interesujące. Tak więc używasz stanu, aby zmienić szablon/kontroler, a stan jest ograniczony do aplikacji. Problem rozwiązany. Ale poczekaj! Jak zakładki! =) –

+0

Co oznacza zakładka w tym przypadku? Nadal masz kontrolę nad adresem URL za pośrednictwem lokalizacji $, ale nie jestem pewien, czy rozumiem Twoje zamiary. –

+0

Przypadek użycia: Aplikacja aplikacji obciążeń aplikacji Aggregating. W ramach paska możesz znajdować się w stanie A, B lub C. Użytkownik jest w stanie Bar + C i chce utworzyć zakładkę w przeglądarce. Używając stanu, adresy URL dla Bar + A, Bar + B i Bar + C są takie same. –

Powiązane problemy