Existe-t-il un moyen d’ajouter par programme des états à $ stateProvider après la configuration du module, par ex. un service ?
Pour ajouter plus de contexte à cette question, je peux utiliser deux approches:
Définition de l'Etat
.state('index.resource.view', {
url: "/:resourceName/view?pageNumber&pageSize&orderBy&search",
templateUrl: "/resourceAdministration/views/view.html",
controller: "resourceViewCtrl",
reloadOnSearch: false,
})
Normalement, les états sont ajoutés au $stateProvider
pendant la phase de configuration. Si vous souhaitez ajouter des états au moment de l'exécution, vous devez conserver une référence à la commande $stateProvider
environ.
Ce code n'a pas été testé, mais doit faire ce que vous voulez. Il crée un service appelé runtimeStates
. Vous pouvez l'injecter dans le code d'exécution, puis ajouter des états.
// config-time dependencies can be injected here at .provider() declaration
myapp.provider('runtimeStates', function runtimeStates($stateProvider) {
// runtime dependencies for the service can be injected here, at the provider.$get() function.
this.$get = function($q, $timeout, $state) { // for example
return {
addState: function(name, state) {
$stateProvider.state(name, state);
}
}
}
});
J'ai implémenté des éléments appelés Etats futurs dans I-Router Extras qui s'occupent de certains cas critiques pour vous comme mapper les urls sur des états qui n'existent pas encore. Les états futurs montrent également comment vous pouvez charger paresseux le code source pour les états d'exécution. Jetez un coup d'œil à code source pour avoir une idée de ce que cela implique.
Dans UI-Router 1.0, les états peuvent être enregistrés et désenregistrés à l'exécution à l'aide de StateRegistry.register
et StateRegistry.deregister
.
Pour avoir accès à StateRegistry, injectez-le sous la forme $stateRegistry
, ou injecter $uiRouter
et y accéder via UIRouter.stateRegistry
.
UI-Router 1.0 inclut également les états futurs prêts à l'emploi qui permettent de charger paresseusement les définitions d'état, voire de les synchroniser par URL.
Chris T l'a cloué! Le fournisseur est la voie à suivre. Vous n'avez pas à le glisser sur l'objet window, économiseur, plus protégé, etc.
Les références croisées de sa réponse avec cet article ont vraiment aidé: http://blog.xebia.com/2013/09/01/differences-between-providers-in-angularjs/#provider
La solution rend un module spécifique $ stateProvider lors du bloc de configuration accessible aux autres modules lors de leurs blocs d'exécution.
Dans ma situation, je génère dynamiquement des états de tableau de bord en fonction des autorisations d'un utilisateur.
Au cours de mon bloc de configuration, mon fournisseur est défini, en passant par le fournisseur stateProvider du module (auquel il faudra accéder ultérieurement).
//in dashboard.module.js
var dashboardModule = angular.module('app.modules.dashboard',[
'app.modules.dashboard.controllers',
'app.modules.dashboard.services',
'app.modules.dashboard.presentations.mileage'
])
.provider('$dashboardState', function($stateProvider){
this.$get = function(PATHS, $state){
return {
addState: function(title, controllerAs, templatePrefix) {
$stateProvider.state('dashboard.' + title, {
url: '/' + title,
views: {
'dashboardModule@dashboard': {
templateUrl: PATHS.DASHBOARD + (templatePrefix ? templatePrefix + '/' : '/') + title + '/' + title + '.view.html',
controller: controllerAs ? controllerAs : null
}
}
});
}
}
}
});
Cela rendra mon fournisseur d'état Dashboard disponible à d'autres modules, au lieu de le claquer sur la fenêtre.
Ensuite, dans le bloc d'exécution de mon module utilisateur (contrôleur), je peux accéder au fournisseur d'état du tableau de bord et injecter des états de manière dynamique.
var UserControllers = angular.module('app.modules.user.controllers', [])
.controller("UserLoginController", ["$state", "$dashboardState", function($state, $dashboardState){
$dashboardState.addState('faq', null, 'content');
$state.go('dashboard.faq');
}]);
Oui, c'est possible, mais comme il y a des couches de cache impliquées, c'est complexe. Alex Feinberg a documenté une solution sur son blog ici:
La fin de l'article inclut un exemple de création d'un état à l'aide de stateProvider:
app.stateProvider.state(ent.lob.name.toLowerCase(), {
url: '/' + ent.lob.name.toLowerCase(),
controller: ent.lob.name.toLowerCase() + 'Controller',
templateUrl: 'lobs/views/' + ent.lob.name.toLowerCase() + '.html'
});