web-dev-qa-db-fra.com

Utilisation des méthodes $ state avec $ stateChangeStart toState et fromState dans Angular ui-router

J'écris un gestionnaire pour $stateChangeStart:

var stateChangeStartHandler = function(e, toState, toParams, fromState, fromParams) {
    if (toState.includes('internal') && !$cookies.MySession) {
        e.preventDefault();
        // Some login stuff.
    }
};

$rootScope.$on('$stateChangeStart', stateChangeStartHandler);

toState n'a pas la méthode includes. Devrais-je faire quelque chose de différent ou y a-t-il un moyen de faire ce que j'essaie de faire?

En outre, lorsque // certains éléments de connexion incluent un $state.go(...), je reçois une boucle infinie. Qu'est-ce qui pourrait causer ça?


Voici un exemple plus complet démontrant ce que nous avons finalement mis au travail:

angular.module('test', ['ui.router', 'ngCookies'])
.config(['$stateProvider', '$cookiesProvider', function($stateProvider, $cookiesProvider) {

    $stateProvider
    .state('public', {
        abstract: true
    })
    .state('public.login', {
        url: '/login'
    })
    .state('tool', {
        abstract: true
    })
    .state('tool.suggestions', {
        url: '/suggestions'
    });

}])
.run(['$state', '$cookies', '$rootScope', function($state, $cookies, $rootScope) {
    $rootScope.$on('$stateChangeStart', function(e, toState, toParams, fromState, fromParams) {

        if (toState.name.indexOf('tool') > -1 && !$cookies.Session) {
            // If logged out and transitioning to a logged in page:
            e.preventDefault();
            $state.go('public.login');
        } else if (toState.name.indexOf('public') > -1 && $cookies.Session) {
            // If logged in and transitioning to a logged out page:
            e.preventDefault();
            $state.go('tool.suggestions');
        };
    });
});

Je n'aime pas utiliser indexOf pour rechercher un état particulier dans le toState. C'est naïf. Je ne sais pas pourquoi toState et fromState ne pourraient pas être une instance du service $state, Ni pourquoi le service $state Ne pouvait pas accepter remplacement de configuration d'état dans ses méthodes.

La boucle infinie a été causée par une erreur de notre part. Je n'aime pas cela, alors je cherche toujours de meilleures réponses.

34
Nick Sloan

Suggestion 1

Lorsque vous ajoutez un objet à $stateProvider.state cet objet est ensuite passé avec l'état. Vous pouvez donc ajouter des propriétés supplémentaires que vous pourrez lire plus tard, si nécessaire.

Exemple de configuration de route

$stateProvider
.state('public', {
    abstract: true,
    module: 'public'
})
.state('public.login', {
    url: '/login',
    module: 'public'
})
.state('tool', {
    abstract: true,
    module: 'private'
})
.state('tool.suggestions', {
    url: '/suggestions',
    module: 'private'
});

Le $stateChangeStart événement vous donne accès aux objets toState et fromState. Ces objets d'état contiendront les propriétés de configuration.

Exemple de contrôle pour la propriété du module personnalisé

$rootScope.$on('$stateChangeStart', function(e, toState, toParams, fromState, fromParams) {
    if (toState.module === 'private' && !$cookies.Session) {
        // If logged out and transitioning to a logged in page:
        e.preventDefault();
        $state.go('public.login');
    } else if (toState.module === 'public' && $cookies.Session) {
        // If logged in and transitioning to a logged out page:
        e.preventDefault();
        $state.go('tool.suggestions');
    };
});

Je n'ai pas changé la logique des cookies parce que je pense que cela dépasse la portée de votre question.

Suggestion 2

Vous pouvez créer un assistant pour vous permettre de travailler de manière plus modulaire.

Valeur publicStates

myApp.value('publicStates', function(){
    return {
      module: 'public',
      routes: [{
        name: 'login', 
        config: { 
          url: '/login'
        }
      }]
    };
});

Valeur privateStates

myApp.value('privateStates', function(){
    return {
      module: 'private',
      routes: [{
        name: 'suggestions', 
        config: { 
          url: '/suggestions'
        }
      }]
    };
});

L'aide

myApp.provider('stateshelperConfig', function () {
  this.config = {
    // These are the properties we need to set
    // $stateProvider: undefined
    process: function (stateConfigs){
      var module = stateConfigs.module;
      $stateProvider = this.$stateProvider;
      $stateProvider.state(module, {
        abstract: true,
        module: module
      });
      angular.forEach(stateConfigs, function (route){
        route.config.module = module;
        $stateProvider.state(module + route.name, route.config);
      });
    }
  };

  this.$get = function () {
    return {
      config: this.config
    };
  };
});

Vous pouvez maintenant utiliser l'assistant pour ajouter la configuration d'état à votre configuration d'état.

myApp.config(['$stateProvider', '$urlRouterProvider', 
    'stateshelperConfigProvider', 'publicStates', 'privateStates',
  function ($stateProvider, $urlRouterProvider, helper, publicStates, privateStates) {
    helper.config.$stateProvider = $stateProvider;
    helper.process(publicStates);
    helper.process(privateStates);
}]);

De cette façon, vous pouvez résumer le code répété et proposer une solution plus modulaire.

Note: le code ci-dessus n'est pas testé

69
1st4ck