Öffnen Sie eine bereits gebootete Anwendung erneut und fügen Sie Abhängigkeiten hinzu

89

Gibt es eine Möglichkeit, eine späte Abhängigkeit in ein bereits gebootetes Winkelmodul einzufügen? Folgendes meine ich:

Angenommen, ich habe eine Website-weite Winkel-App, definiert als:

// in app.js
var App = angular.module("App", []);

Und auf jeder Seite:

<html ng-app="App">

Später öffne ich die App erneut, um Logik hinzuzufügen, die auf den Anforderungen der aktuellen Seite basiert:

// in reports.js
var App = angular.module("App")
App.controller("ReportsController", ['$scope', function($scope) {
  // .. reports controller code
}])

Nun, sagen , dass einer dieser On-Demand - Bits der Logik auch ihre eigenen Abhängigkeiten erfordert (wie ngTouch, ngAnimate, ngResourceusw.). Wie kann ich sie an die Basis-App anhängen? Das scheint nicht zu funktionieren:

// in reports.js
var App = angular.module("App", ['ui.event', 'ngResource']); // <-- raise error when App was already bootstrapped

Mir ist klar, dass ich alles im Voraus tun kann, dh -

// in app.js
var App = angular.module("App", ['ui.event', 'ngResource', 'ngAnimate', ...]);

Oder definieren Sie jedes Modul für sich und fügen Sie dann alles in die Haupt-App ein ( siehe hier für weitere Informationen ):

// in reports.js
angular.module("Reports", ['ui.event', 'ngResource'])
.controller("ReportsController", ['$scope', function($scope) {
  // .. reports controller code
}])

// in home.js
angular.module("Home", ['ngAnimate'])
.controller("HomeController", ['$scope', '$http', function($scope, $http){
  // ...
}])

// in app.js, loaded last into the page (different for every page that varies in dependencies)
var App = angular.module("App", ['Reports', 'Home'])

Dafür muss ich die App jedoch jedes Mal mit den Abhängigkeiten der aktuellen Seite initialisieren.

Ich ziehe den Grund enthalten app.jsin jeder Seite und einfach einzuführen , um die erforderlichen Erweiterungen auf jeder Seite ( reports.js, home.jsusw.), ohne dass die Bootstrap - Logik jedes Mal zu überarbeiten, die ich hinzufügen oder entfernen etwas.

Gibt es eine Möglichkeit, Abhängigkeiten einzuführen, wenn die App bereits gebootet ist? Was ist der idiomatische Weg (oder die idiomatischen Wege), dies zu tun? Ich neige zu letzterer Lösung, wollte aber sehen, ob die von mir beschriebene Vorgehensweise auch möglich ist. Vielen Dank.

sa125
quelle
Können Sie mir Ihren endgültigen Arbeitscode geben, um ihn mir anzusehen?
Mangu Singh Rajpurohit
@ user2393267 mmm, war so lange her, ich habe keine Ahnung, ob ich diesen Code noch habe ... Entschuldigung. Ich glaube, ich habe das Design irgendwann noch einmal überarbeitet, denn normalerweise bedeutet es, wenn ich Dinge durchhacken muss, dass ich es nicht richtig mache ... Wenn Sie jedoch immer noch entschlossen sind, diesen Ansatz zu verfolgen, scheint die folgende Antwort ein guter Hinweis zu sein .
Sa125

Antworten:

115

Ich habe es so gelöst:

Verweisen Sie erneut auf die App:

var app = angular.module('app');

Verschieben Sie dann Ihre neuen Anforderungen in das Anforderungsarray:

app.requires.push('newDependency');
AlBaraa Sh
quelle
3
Dies funktioniert für mich +1 Ich habe dies für mehrere Abhängigkeiten verwendet, wie z. B. app.requires.push ('doctorCtrl', 'doctorService');
Amir
8
Das hat meine Architektur gerettet.
Saeed Neamati
3
Es funktioniert nicht für mich. Ich füge die Abhängigkeit dynamisch wie beschrieben hinzu, aber Angular kann immer noch keinen Dienst aus dem hinzugefügten Modul finden.
Slava Fomin II
6
Und app.requiresist ein Array. Wenn Sie also mehrere Abhängigkeiten hinzufügen (wie in Ihrem Berichtsbeispiel), übergeben Sie diese als separate Argumente an die pushMethode: app.requires.push('ui.event', 'ngResource');oder wenn Ihre zusätzlichen Abhängigkeiten bereits ein Array sind:Array.prototype.push.apply(app.requires, ['ui.event', 'ngResource'])
The Red Pea
2
Ich überspringe manchmal die Abstimmung, weil ich mich nicht anmelden möchte, diesmal nicht! Vielen Dank!
CularBytes
12

Einfach ... Holen Sie sich eine Instanz des Moduls mit dem Getter wie folgt: var app = angular.module ("App");

Fügen Sie dann der Sammlung "require" Folgendes hinzu: app.requires [app.requires.length] = "ngResource";

Jedenfalls hat das bei mir funktioniert. VIEL GLÜCK!

David Donovan
quelle
4
Das hat bei mir funktioniert! Ich habe eine Frage - warum nicht: app.requires.push ("ngResource")?
Philipp Munin
9

Nach diesem Vorschlag in der Google-Gruppe Angular JS ist diese Funktionalität derzeit nicht verfügbar. Hoffentlich beschließt das Kernteam, diese Funktionalität hinzuzufügen, könnte sie selbst verwenden.

Matt Nibecker
quelle
4
Ja, dies scheint besonders nützlich für Leute zu sein, die nicht unbedingt ein SPA bauen möchten.
Regularmike
4

Wenn Sie mehrere Abhängigkeiten gleichzeitig hinzufügen möchten, können Sie diese wie folgt per Push übergeben:

<script>
    var app = angular.module('appName');
    app.requires.push('dependencyCtrl1', 'dependencyService1');
</script>
Amir
quelle
4

Mir ist klar, dass dies eine alte Frage ist, es wurde jedoch noch keine funktionierende Antwort gegeben. Deshalb habe ich beschlossen, mitzuteilen, wie ich sie gelöst habe.

Die Lösung erfordert das Gabeln von Angular, sodass Sie CDN nicht mehr verwenden können. Die Modifikation ist jedoch sehr klein, daher bin ich überrascht, warum diese Funktion in Angular nicht vorhanden ist.

Ich folgte dem Link zu Google-Gruppen , der in einer der anderen Antworten auf diese Frage angegeben war. Dort fand ich den folgenden Code, der das Problem löste:

instanceInjector.loadNewModules = function (mods) {
  forEach(loadModules(mods), function(fn) { instanceInjector.invoke(fn || noop); });
};

Als ich diesen Code in Zeile 4414 im eckigen 1.5.0-Quellcode (innerhalb der createInjectorFunktion vor der return instanceInjector;Anweisung) hinzufügte, konnte ich nach diesem Bootstrapping Abhängigkeiten hinzufügen $injector.loadNewModules(['ngCookies']);.

tjespe
quelle
? Was ist falsch an der Antwort mit der höchsten Stimme (Stand 26.06.2017) ? Es sieht so aus, als ob es mehr als ein Jahr vor Ihrer Veröffentlichung bereitgestellt wurde. Hat Ihre Antwort einen Vorteil?
Die rote Erbse
@ TheRedPea Nun, es ist nichts falsch daran, außer dass es mein Problem nicht gelöst hat, aber diese Antwort hat
tjespe
Und es hat bei Ihnen nicht funktioniert, weil Sie Ihre App vermutlich bereits gebootet haben? Ich habe das auch beobachtet ...
Die rote Erbse
2
Nach dem Lesen des verlinkten Google Community-Beitrags bin ich mir noch sicherer, dass Bootstrapping der Grund ist, warum eine solche Lösung erforderlich ist. Upvoting, weil die ursprüngliche Frage nach einer "bereits gebooteten Anwendung" gestellt wurde, die sonst niemand anspricht (tatsächlich hat das OP möglicherweise falsch gesprochen)
The Red Pea
1

Seit Version 1.6.7 ist es nun möglich, Module verzögert zu laden, nachdem die App mit gebootet wurde $injector.loadNewModules([modules]). Unten finden Sie ein Beispiel aus der AngularJS-Dokumentation:

app.factory('loadModule', function($injector) {
   return function loadModule(moduleName, bundleUrl) {
     return getScript(bundleUrl).then(function() { $injector.loadNewModules([moduleName]); });
   };
})

Bitte lesen Sie die vollständige Dokumentation zu loadNewModules, da es einige Fallstricke gibt.

Es gibt auch eine sehr gute Beispiel-App von Omkadiri , die sie mit dem UI -Router verwendet.

Denis Pshenov
quelle