web-dev-qa-db-fra.com

AngularJS - Routeur d'interface utilisateur - ajouter par programme des états

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:

  1. essayez de forcer le rechargement sur l'état défini dans la configuration du module, le problème est que cet état a un reloadOnSearch défini sur false, donc quand j'essaie $ state.go ('state.name', {new: param}, {reload: true}); rien ne se passe, des idées?

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,
})
  1. essayez d’ajouter par programme les états que je dois charger à partir d’un service afin que le routage puisse fonctionner correctement. Je préférerais utiliser la première option si possible.
53
khorvat

Voir -edit- pour des informations mises à jour

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.

-edit- pour UI-Router 1.0+

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.

109
Chris T

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');

}]);
14
Alex Boisselle

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:

http://alexfeinberg.wordpress.com/2014/03/08/dynamically-populating-angular-ui-router-states-from-a-service/

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'
});
4
Chad Robinson