rouvrir et ajouter des dépendances à une application déjà amorcée

89

Existe-t-il un moyen d'injecter une dépendance tardive à un module angulaire déjà amorcé? Voici ce que je veux dire:

Dites que j'ai une application angulaire à l'échelle du site, définie comme:

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

Et dans chaque page:

<html ng-app="App">

Plus tard, je rouvre l'application pour ajouter une logique basée sur les besoins de la page actuelle:

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

Maintenant, dire que l' un de ces bits sur la demande de la logique exige également leurs propres dépendances (comme ngTouch, ngAnimate, ngResource, etc.). Comment puis-je les attacher à l'application de base? Cela ne semble pas fonctionner:

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

Je me rends compte que je peux tout faire à l'avance, c'est-à-dire -

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

Ou définissez chaque module seul, puis injectez tout dans l'application principale ( voir ici pour plus ):

// 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'])

Mais cela nécessitera d'initialiser l'application à chaque fois avec les dépendances de la page actuelle.

Je préfère inclure la base app.jsdans chaque page et présenter simplement les extensions nécessaires à chaque page ( reports.js, home.js, etc.), sans avoir à réviser la logique à chaque fois de bootstrapping ajouter ou quelque chose supprimer.

Existe-t-il un moyen d'introduire des dépendances lorsque l'application est déjà amorcée? Quelle est la ou les manières idiomatiques de procéder? Je penche vers cette dernière solution, mais je voulais voir si la façon dont je l'ai décrite pouvait également être réalisée. Merci.

sa125
la source
Pouvez-vous me donner votre code de travail final, pour y jeter un coup d'œil?
Mangu Singh Rajpurohit
@ user2393267 mmm, ça fait si longtemps, je ne sais pas si j'ai toujours ce code ... Désolé. Je pense que j'ai finalement revisité le design, car généralement, quand je dois pirater des choses, cela signifie que je ne le fais pas correctement ... Cependant, si vous êtes toujours déterminé à poursuivre cette approche, la réponse ci-dessous semble être une bonne piste .
sa125 du

Réponses:

115

Je l'ai résolu comme ceci:

référence à nouveau l'application:

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

puis transmettez vos nouvelles exigences au tableau des exigences:

app.requires.push('newDependency');
AlBaraa Sh
la source
3
Cela fonctionne pour moi +1 J'ai utilisé ceci pour des dépendances multiples comme app.requires.push ('doctorCtrl', 'doctorService');
Amir
8
Cela a sauvé mon architecture.
Saeed Neamati le
3
Ça ne fonctionne pas pour moi. J'ajoute la dépendance dynamiquement comme décrit, mais Angular ne trouve toujours pas de service dans le module ajouté.
Slava Fomin II
6
Et app.requiresc'est un tableau, donc si vous ajoutez plusieurs dépendances (comme dans votre exemple Reports), vous les passez en tant qu'arguments séparés à la pushméthode: app.requires.push('ui.event', 'ngResource');ou si vos dépendances supplémentaires sont déjà un tableau:Array.prototype.push.apply(app.requires, ['ui.event', 'ngResource'])
The Red Pea
2
Je saute parfois le vote parce que je ne veux pas me connecter, pas cette fois! Merci!
CularBytes
12

Simple ... Obtenez une instance du module en utilisant le getter comme ceci: var app = angular.module ("App");

Puis ajoutez à la collection "requires" comme ceci: app.requires [app.requires.length] = "ngResource";

Quoi qu'il en soit, cela a fonctionné pour moi. BONNE CHANCE!

David Donovan
la source
4
Cela a fonctionné pour moi! J'ai une question - pourquoi ne pas utiliser: app.requires.push ("ngResource")?
Philipp Munin
9

Selon cette proposition sur le groupe Google Angular JS, cette fonctionnalité n'existe pas pour le moment. J'espère que l'équipe de base décide d'ajouter cette fonctionnalité et pourra l'utiliser moi-même.

Matt Nibecker
la source
4
Oui, cela semble particulièrement utile pour les personnes qui ne souhaitent pas nécessairement construire un SPA.
regularmike
4

Si vous souhaitez ajouter plusieurs dépendances à la fois, vous pouvez les transmettre en push comme suit:

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

Je me rends compte que c'est une vieille question, cependant, aucune réponse de travail n'a encore été fournie, alors j'ai décidé de partager comment je l'ai résolue.

La solution nécessite de forger Angular, vous ne pouvez donc plus utiliser CDN. Cependant, la modification est très petite, je suis donc surpris de savoir pourquoi cette fonctionnalité n'existe pas dans Angular.

J'ai suivi le lien vers les groupes Google qui a été fourni dans l' une des autres réponses à cette question. Là, j'ai trouvé le code suivant, qui a résolu le problème:

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

Lorsque j'ai ajouté ce code à la ligne 4414 dans le code source angulaire 1.5.0 (à l'intérieur de la createInjectorfonction, avant l' return instanceInjector;instruction), cela m'a permis d'ajouter des dépendances après le démarrage comme celui-ci $injector.loadNewModules(['ngCookies']);.

tjespe
la source
? Quel est le problème avec la réponse la plus votée (au 26/06/2017) ? Il semble qu'il a été fourni plus d'un an avant que vous ne publiiez ceci; votre réponse a-t-elle un avantage?
The Red Pea
@TheRedPea Eh bien, il n'y a rien de mal à cela, sauf que cela n'a pas résolu mon problème, mais cette réponse l'a fait
tjespe
Et cela n'a pas fonctionné pour vous parce que, je suppose, vous aviez déjà bootatrappé votre application? J'ai observé ça aussi ...
The Red Pea
2
Après avoir lu l'article lié à la communauté Google, je suis encore plus sûr que le bootstrap est la raison pour laquelle une solution comme celle-ci est nécessaire. Vote positif parce que la question initiale portait sur une "application déjà amorcée", à laquelle personne d'autre ne répond (en effet, l'OP peut avoir mal exprimé)
The Red Pea
1

Depuis la version 1.6.7, il est désormais possible de charger les modules paresseux après le démarrage de l'application à l'aide de $injector.loadNewModules([modules]). Voici un exemple tiré de la documentation AngularJS:

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

Veuillez lire la documentation complète sur loadNewModules car il y a des pièges autour de lui.

Il existe également un très bon exemple d'application d'Omkadiri qui l' utilise avec ui-router.

Denis Pshenov
la source